(單鏈表)單鏈表的整體逆序和局部逆序


  • 題目一:將單鏈表翻轉。
  • 思路:有三種方式。
    • 一:用數組存儲單鏈表的值,然后重新逆序賦值,效率較低。
    • 二:利用三個指針,在原來的基礎上進行逆序。這種方法比較實用,效率也高。
    • 三:從第2個節點到第N個節點,依次逐節點插入到第1個節點(head節點)之后,最后將第一個節點挪到新表的表尾。需要新建一個鏈表,這種方法和第二種差不多。
    • 這里我就寫出第二種方法,比較實用。
  • 代碼(方法二):
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
    ListNode *ReverseList(ListNode *head){
        ListNode *pre, *cur, *net;//前驅,中間,后繼節點。
        pre = head;
        cur = pre->next;
        while (cur){
            net = cur->next;
            cur->next = pre;
            pre = cur;
            cur = net;
        }
        //這里翻轉完成之后起初的頭結點就是尾節點了。所以
        head->next = NULL;
        *head = p1;
        return head;
    }

     

  • 問題二;
    給定鏈接列表,每次顛倒鏈表k的節點並返回其修改的列表。
    
    如果節點的數量不是k的倍數,則最后的左出節點應該保持原樣。
    
    您不能更改節點中的值,只有節點本身可能會更改。
    
    只允許常量存儲器。
    
    例如,
    給定這個鏈表:1-> 2-> 3-> 4-> 5
    
    對於k = 2,您應該返回:2-> 1-> 4-> 3-> 5
    
    對於k = 3,您應該返回:3-> 2-> 1-> 4-> 5

    •   解題思路:這里實用了常量數組存儲鏈表的值,然后進行局部鏈表的翻轉,利用reverse函數進行翻轉。
    •   代碼
      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode(int x) : val(x), next(NULL) {}
       * };
       */
      class Solution {
      public:
          ListNode *reverseKGroup(ListNode *head, int k) {
              if (!head) 
                  return head;
              if (k == 1)
                  return head;
              vector<int> res;
              ListNode *temp = head;
              ListNode *newhead = head;
              while (temp){
                  res.push_back(temp->val);
                  temp = temp->next;
              }
              
              for (int i=0; i+k<=res.size(); i+=k){
                  reverse(res.begin()+i, res.begin()+i+k);
              }
              
              for (int i=0; i<res.size(); i++){
                  newhead->val = res[i];
                  newhead = newhead->next;
              }
              //delete temp;
              return head;
          }
      };

       

  • 問題三:

    將鏈接列表從位置m反轉到n。 做它在就地和一次通過。
    
    例如:
    給定1-> 2-> 3-> 4-> 5-> NULL,m = 2和n = 4,
    
    return1-> 4-> 3-> 2-> 5-> NULL。
    
    注意:
    給定m,n滿足以下條件:
    1≤m≤n≤列表長度。

     

    •   解題思路:這個題目也是局部進行鏈表的翻轉,可以使用數組進行存儲翻轉,但是效率比較低。這個題目純粹的是考察鏈表的基本功問題。我們只要將指定區間里面的部分進行翻轉(和翻轉整個鏈表一樣),設置三個指針,我們這里講指定范圍內最后面的節點依次的往前面移動,這樣就實現了聯煸的翻轉。

    •   代碼:
      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode(int x) : val(x), next(NULL) {}
       * };
       */
      class Solution {
      public:
          ListNode *reverseBetween(ListNode *head, int m, int n) {
              //在指定的范圍之內,將鏈表末端的節點依次插入到前面,實現翻轉。
              if (head == NULL)
                  return head;
              ListNode *dummy = new ListNode(0);//新生成一個新鏈表節點,作為空的頭結點
              dummy->next = head;
              ListNode *pre = dummy;
              for (int i=1; i<m; i++) {
                  pre = pre->next;
              }
              ListNode *cur = pre->next;
              ListNode *net = cur->next;
              //翻轉次數為兩次,依次將后面的元素調取到指定位置前面,指定三個指針來進行操作即可
              //①:1 2 3 4 5 -> 1 3 2 4 5  將3調到2的前面
              //②:1 3 2 4 5 -> 1 4 3 2 5  將4調到3的前面
              for (int i=0; i<n-m; i++) {//調取次數n-m
                  cur->next = net->next;
                  net->next = pre->next;
                  pre->next = net;
                  net = cur->next;
              }
              return dummy->next;
          }
      };

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM