OJ連接:https://leetcode-cn.com/problems/reverse-linked-list/description/node
// 三個指針翻轉的思路 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { // 鏈表爲空或者只有一個節點不須要翻轉 if(head == NULL || head->next == NULL) return head; ListNode* n1, *n2, *n3; n1 = NULL; n2 = head; n3 = n2->next; //中間節點不爲空,繼續修改指向 while(n2) { //中間節點指向反轉 n2->next = n1; //更新三個連續的節點 n1 = n2; n2 = n3; // 須要注意到最後兩個節點時,n3已經爲空 if(n3) n3 = n3->next; } //返回新的頭 return n1; } }; // 頭插的思路 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* newhead = NULL; ListNode* cur = head; while(cur) { struct ListNode* next = cur->next; //頭插新節點,更新頭 cur->next = newhead; newhead = cur; cur = next; } return newhead; } };
OJ連接:https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId=49&&tqId=29370&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking面試
須要注意本題要求了複雜度爲O(N),空間複雜度爲O(1)數組
一、本題說明了鏈表的長度小於900,因此這裏咱們能夠開闢一個900個空間的數組,將鏈表的數據放到數組中再進行判斷。這種方法雖然能過OJ,可是實際面試中是不符合面試官的要求的。dom
二、經過slow走一步,fast走兩步,找到中間節點。而後將後半段鏈表反轉,反轉後的鏈表跟原鏈表對比是否相同,相同則是迴文結構。這樣寫才知足上面的對複雜度的要求。ide
/* 此題也能夠先把鏈表中的元素值所有保存到數組中,而後再判斷數組是否爲迴文。不建議使用這種解法,由於若是沒有告訴鏈表最大長度,則不能同此解法 */ class PalindromeList { public: bool chkPalindrome(ListNode* A) { // write code here int a[900] = {0}; ListNode* cur = A; int n = 0; //保存鏈表元素 while(cur) { a[n++] = cur->val; cur = cur->next; } //判斷數組是否爲迴文結構 int begin = 0, end = n-1; while(begin < end) { if(a[begin] != a[end]) return false; ++begin; --end; } return true; } }; /* 解題思路: 此題能夠先找到中間節點,而後把後半部分逆置,最近先後兩部分一一比對,若是節點的值所有相同,則即爲迴文。 */ class PalindromeList { public: bool chkPalindrome(ListNode* A) { if (A == NULL || A->next == NULL) return true; ListNode* slow, *fast, *prev, *cur, *nxt; slow = fast = A; //找到中間節點 while (fast && fast->next) { slow = slow->next; fast = fast->next->next; } prev = NULL; //後半部分逆置 cur = slow; while (cur) { nxt = cur->next; cur->next = prev; prev = cur; cur = nxt; } //逐點比對 while (A && prev) { if (A->val != prev->val) return false; A = A->next; prev = prev->next; } return true; } };
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; */ /* 解題思路: 此題能夠先找出相同節點的區間,而後刪除區間中的全部值,直到把鏈表遍歷完結束 */ class Solution { public: ListNode* deleteDuplication(ListNode* pHead) { if(pHead == NULL || pHead->next == NULL) return pHead; ListNode* n1 = NULL; ListNode* n2 = pHead; ListNode* n3 = n2->next; while(n3 != NULL) { //若是相鄰節點不相同,則不須要刪除,更新節點,繼續向後遍歷 if(n2->val != n3->val) { n1 = n2; n2 = n3; n3 = n3->next; } else { //若是相鄰節點相同 //則n3去找第一個不相同的節點 while(n3 && n3->val == n2->val) { n3 = n3->next; } //從新連接,若是要刪除的包括頭節點,則更新頭節點 if(n1) n1->next = n3; else pHead = n3; // 刪除掉重複的節點 while(n2 != n3) { ListNode* next = n2->next; delete n2; n2 = next; } //更新節點 n2 = n3; if(n3) n3 = n3->next; } } return pHead; } };
OJ連接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/description/指針
此題能夠分三步進行:code
/* // Definition for a Node. class Node { public: int val; Node* next; Node* random; Node(int _val) { val = _val; next = NULL; random = NULL; } }; */ class Solution { public: Node* copyRandomList(Node* head) { // 1.拷貝鏈表,並插入到原節點的後面 Node* cur = head; while(cur) { Node* copy = new Node(cur->val); Node* next = cur->next; // 插入 cur->next = copy; copy->next = next; // 迭代往下走 cur = next; } // 2.置拷貝節點的random cur = head; while(cur) { Node* copy = cur->next; if(cur->random != NULL) copy->random = cur->random->next; else copy->random = NULL; cur = copy->next; } // 3.解拷貝節點,連接拷貝節點 Node* copyHead = NULL, *copyTail = NULL; cur = head; while(cur) { Node* copy = cur->next; Node* next = copy->next; // copy解下來尾插連接到拷貝節點 if(copyTail == NULL) { copyHead = copyTail = copy; } else { copyTail->next = copy; copyTail = copy; } cur->next = next; cur = next; } return copyHead; } };
/*思路跟上面的方法基本一致,差異再也不是拷貝節點掛在原節點後面創建映射關係,而是經過將原節點和拷貝節點存儲到map中創建映射關係,這樣也是經過3步就能夠複製出拷貝鏈表*/ // 1.拷貝鏈表,使用map創建原鏈表節點和拷貝節點的映射 // 2.置拷貝節點的random. 經過map找到node->random的拷貝節點,就能夠值copy節點的random。 // 3.從map中找到拷貝節點,連接拷貝節點 // Definition for a Node. class Node { public: int val; Node* next; Node* random; Node(int _val) { val = _val; next = NULL; random = NULL; } }; */ class Solution { public: Node* copyRandomList(Node* head) { map<Node*, Node*> nodeCopyMap; // 1.拷貝鏈表,使用map創建原鏈表節點和拷貝節點的映射 Node* cur = head; while(cur) { Node* copy = new Node(cur->val); nodeCopyMap[cur] = copy; cur = cur->next; } // 2.置拷貝節點的random cur = head; while(cur) { Node* copy = nodeCopyMap[cur]; if(cur->random != NULL) copy->random = nodeCopyMap[cur->random]; else copy->random = NULL; cur = cur->next; } // 3.從map中找到拷貝節點,連接拷貝節點 Node* copyHead = NULL, *copyTail = NULL; cur = head; while(cur) { // 找到cur映射的拷貝節點 Node* copy = nodeCopyMap[cur]; if(copyTail == NULL) { copyHead = copyTail = copy; } else { copyTail->next = copy; copyTail = copy; } cur = cur->next; } return copyHead; } };
若是你看了之後不是很明白,你能夠點擊看下面的視頻講解:
視頻講解(鼠標點這裏)視頻