- 題目一:將單鏈表翻轉。
- 思路:有三種方式。
- 一:用數組存儲單鏈表的值,然后重新逆序賦值,效率較低。
- 二:利用三個指針,在原來的基礎上進行逆序。這種方法比較實用,效率也高。
- 三:從第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; } };
- 解題思路:這個題目也是局部進行鏈表的翻轉,可以使用數組進行存儲翻轉,但是效率比較低。這個題目純粹的是考察鏈表的基本功問題。我們只要將指定區間里面的部分進行翻轉(和翻轉整個鏈表一樣),設置三個指針,我們這里講指定范圍內最后面的節點依次的往前面移動,這樣就實現了聯煸的翻轉。