题目
反转一个单向链表。
难度:容易
编程语言:C++
分析
程序框架为:
1 2 3 4 5 6 7 8 9 10 11 12 13
| struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode* reverseList(ListNode* head) { } };
|
我们先把问题具体化,比如现在有一个单向链表 1 -> 2 -> 3 -> 4 -> 5,要反转为 5 -> 4 -> 3 -> 2 -> 1。
单向链表在内存中的存储见下图:
+---+-----+ +---+-----+ +---+-----+ +---+-----+ +---+------+
value / *next | 1 | 102 | | 2 | 103 | | 3 | 104 | | 4 | 105 | | 5 | NULL |
+---+-----+ +---+-----+ +---+-----+ +---+-----+ +---+------+
adress 101 102 103 104 105
反转为 5 -> 4 -> 3 -> 2 -> 1 后,在内存中的存储见下图:
+---+------+ +---+-----+ +---+-----+ +---+-----+ +---+-----+
value / *next | 1 | NULL | | 2 | 101 | | 3 | 102 | | 4 | 103 | | 5 | 104 |
+---+------+ +---+-----+ +---+-----+ +---+-----+ +---+-----+
adress 101 102 103 104 105
也可以是:
+---+-----+ +---+-----+ +---+-----+ +---+-----+ +---+------+
value / *next | 5 | 102 | | 4 | 103 | | 3 | 104 | | 2 | 105 | | 1 | NULL |
+---+-----+ +---+-----+ +---+-----+ +---+-----+ +---+------+
adress 101 102 103 104 105
所以我们分开两个方法写,一是反转指针,二是反转值。
方法一:反转指针
反转指针,需要用一个 vector 保存所有元素的地址。用上图的示例,即是 vector 保存 [NULL, 101, 102, 103, 104],然后把:
- 105 的 *next 设为 104
- 104 的 *next 设为 103
- 103 的 *next 设为 102
- 102 的 *next 设为 101
- 101 的 *next 设为 NULL
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ListNode* reverseList(ListNode* head) { if (head == NULL) { return NULL; } // 把各个节点地址添加到 vector vector<ListNode*> nodes; nodes.push_back(NULL); // 作为首元素在反转后的 *next while (head->next != NULL) { nodes.push_back(head); head = head->next; } // 此时 head->next == NULL,即是到达末尾元素 ListNode* tail = head; // 用来返回的 for (int i = nodes.size() - 1; i >=0; i--) { head->next = nodes[i]; head = head->next; } return tail; }
|
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <iostream> #include <vector> using namespace std; struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; void printLinkedlist(ListNode* head) { while (head != NULL) { cout << head->val << " "; head = head->next; } cout << endl; } class Solution { public: ListNode* reverseList(ListNode* head) { if (head == NULL) { return head; } vector<ListNode*> nodes; nodes.push_back(NULL); while (head->next != NULL) { nodes.push_back(head); head = head->next; } ListNode* tail = head; for (int i = nodes.size() - 1; i >= 0; i--) { head->next = nodes[i]; head = head->next; } return tail; } }; int main() { ListNode n1(1); ListNode n2(2); ListNode n3(3); ListNode n4(4); ListNode n5(5); n1.next = &n2; n2.next = &n3; n3.next = &n4; n4.next = &n5; printLinkedlist(&n1); Solution sol; ListNode* head = sol.reverseList(&n1); printLinkedlist(head); }
|
提交到 Leetcode,Accepted! :) 运行时间为 8ms。
方法二:反转值
反转值的思路是,不改变指针的指向,只反转各个节点的 val。
- 先遍历整个 Linkedlist,把各个节点的 val 保存到 vector。
- 再遍历一次 Linkedlist,把 vector 的 val 倒序赋值到各个节点就可以了。
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ListNode* reverseList(ListNode* head) { if (head == NULL) { return NULL; } // 遍历整个 Linkedlist,把各个节点的 val 保存到 vector vector<int> nodeVals; ListNode* tempHead = head; while (tempHead != NULL) { nodeVals.push_back(tempHead->val); tempHead = tempHead->next; } // 遍历一次 Linkedlist,把 vector 的 val 倒序赋值到各个节点 tempHead = head; int lastIdx = nodeVals.size() - 1; while (tempHead != NULL) { tempHead->val = nodeVals[lastIdx]; lastIdx--; tempHead = tempHead->next; } return head; }
|
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #include <iostream> #include <vector> using namespace std; struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; void printLinkedlist(ListNode* head) { while (head != NULL) { cout << head->val << " "; head = head->next; } cout << endl; } class Solution { public: ListNode* reverseList2(ListNode* head) { if (head == NULL) { return NULL; } vector<int> nodeVals; ListNode* tempHead = head; while (tempHead != NULL) { nodeVals.push_back(tempHead->val); tempHead = tempHead->next; } tempHead = head; int lastIdx = nodeVals.size() - 1; while (tempHead != NULL) { tempHead->val = nodeVals[lastIdx]; lastIdx--; tempHead = tempHead->next; } return head; } }; int main() { ListNode n1(1); ListNode n2(2); ListNode n3(3); ListNode n4(4); ListNode n5(5); n1.next = &n2; n2.next = &n3; n3.next = &n4; n4.next = &n5; printLinkedlist(&n1); Solution sol; ListNode* head; head = sol.reverseList2(&n1); printLinkedlist(head); }
|
提交到 Leetcode,Accepted! :) 运行时间为 8ms。