链表

链表题,多指针(反转链表),多虚拟头(分隔链表)

 
用集合,先把A链表存进集合,然后遍历B链表,每次判断节点是否在集合里,在的话就是第一个相交,用集合来判断链表公共元素问题太方便了
 1 class Solution {
 2 public:
 3     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
 4         unordered_set<ListNode*> s;
 5         while(headA){
 6             s.insert(headA);
 7             headA = headA->next;
 8  
 9 
10         }
11         while(headB){
12             if(s.count(headB)){
13                 return headB;
14             }
15             headB = headB->next;
16         }
17         return NULL;
18     }
19 };
View Code
 
双指针数学构思,拼接,AB,BA,
 1 class Solution {
 2 public:
 3     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
 4         if (headA == nullptr || headB == nullptr) {
 5             return nullptr;
 6         }
 7         ListNode *pA = headA, *pB = headB;
 8         while (pA != pB) {
 9             pA = pA == nullptr ? headB : pA->next;
10             pB = pB == nullptr ? headA : pB->next;
11         }
12         return pA;
13     }
14 };
15 
16 作者:LeetCode-Solution
17 链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/solution/xiang-jiao-lian-biao-by-leetcode-solutio-a8jn/
18 来源:力扣(LeetCode)
19 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Code

 

题目要求n(logn),所以这边考虑归并排序
先分,再合,合的话就是合并两个有序链表,和合并两个有序数组一样简单
 1 class Solution {
 2 public:
 3     ListNode* sortList(ListNode* head) {
 4          if (!head || !head->next) return head;//0个和1个数的情况
 5         auto slow = head, fast = head;
 6         while (fast->next && fast->next->next)//三个数则进入循环分割
 7             slow = slow->next, fast = fast->next->next;
 8         // 切链
 9         fast = slow->next, slow->next = nullptr;
10         return merge(sortList(head), sortList(fast));
11     }
12 
13      ListNode* merge(ListNode* l1, ListNode* l2) {
14          ListNode* head = new ListNode();
15         ListNode* ptr = head;
16         while (l1 && l2) {
17             auto &node = l1->val < l2->val ? l1 : l2;//&可以同步->next这个操作,其他添加和删除节点功能一样
18             ptr = ptr->next = node, node = node->next;
19         }
20         ptr->next = l1 ? l1 : l2;
21         return head->next;
22     }
23 };
View Code

 存一个别人的七份简洁答案

  1 class Solution {
  2 public:
  3     ListNode* sortList(ListNode* head) {
  4         if (!head || !head->next) return head;
  5         auto slow = head, fast = head;
  6         while (fast->next && fast->next->next)
  7             slow = slow->next, fast = fast->next->next;
  8         // 切链
  9         fast = slow->next, slow->next = nullptr;
 10         return merge(sortList(head), sortList(fast));
 11     }
 12 
 13 private:
 14     ListNode* merge(ListNode* l1, ListNode* l2) {
 15         ListNode sub(0), *ptr = 16         while (l1 && l2) {
 17             auto &node = l1->val < l2->val ? l1 : l2;
 18             ptr = ptr->next = node, node = node->next;
 19         }
 20         ptr->next = l1 ? l1 : l2;
 21         return sub.next;
 22     }
 23 };
 24 红黑树排序
 25 利用STL里面的set容器底层是红黑树实现,来实现树排序
 26 
 27 
 28 class Solution {
 29 public:
 30     ListNode* sortList(ListNode* head) {
 31         multiset<int> worker;
 32         auto sub = head;
 33         while (sub) worker.insert(sub->val),
 34             sub = sub->next;
 35         sub = head;
 36         for (auto &i : worker)
 37             sub->val = i, sub = sub->next;
 38         return head;
 39     }
 40 };
 41 堆排序
 42 也是利用STL里面的优先队列底层是堆排序算法,来实现。
 43 
 44 
 45 class Solution {
 46 public:
 47     ListNode* sortList(ListNode* head) {
 48         priority_queue<int, vector<int>, greater<int>> worker;
 49         auto sub = head;
 50         while (sub) worker.push(sub->val), sub = sub->next;
 51         sub = head;
 52         while (sub) {
 53             sub->val = worker.top(), worker.pop();
 54             sub = sub->next;
 55         }
 56         return head;
 57     }
 58 };
 59 以下代码是力扣因为时间过不了的代码,但是逻辑没问题。大家看看,当扩张思维了。
 60 
 61 代码逻辑都是,把数组当成中间变量来做排序,再最终转化成链表:
 62 链表->数组->链表
 63 
 64 快排
 65 
 66 class Solution {
 67 public:
 68     ListNode* sortList(ListNode* head) {
 69         vector<ListNode*> worker;
 70         ListNode temp(0), *ptr = head;
 71         while (ptr) worker.push_back(ptr), ptr = ptr->next;
 72         quickSort(worker, 0, worker.size() - 1);
 73         ptr = &temp;
 74         for (auto i : worker) ptr = ptr->next = i;
 75         ptr->next = nullptr;
 76         return temp.next;
 77     }
 78 
 79 private:
 80     void quickSort(vector<ListNode*> &worker, int l, int r) {
 81         if (l >= r) return;
 82         int pivot = patition(worker, l, r);
 83         quickSort(worker, l, pivot - 1);
 84         quickSort(worker, pivot + 1, r);
 85     }
 86 
 87     int patition(vector<ListNode*> &worker, int l, int r) {
 88         for (int i = l; i < r; ++i) {
 89             if (worker[i]->val < worker[r]->val)
 90                 swap(worker[l++], worker[i]);
 91         }
 92         swap(worker[l], worker[r]);
 93         return l;
 94     }
 95 };
 96 
 97 class Solution {
 98 public:
 99     ListNode* sortList(ListNode* head) {
100         vector<int> worker;
101         auto sub = head;
102         while (sub) worker.push_back(sub->val),
103             sub = sub->next;
104         quickSort(worker, 0, worker.size() - 1);
105         sub = head;
106         for (auto &i : worker)
107             sub->val = i, sub = sub->next;
108         return head;
109     }
110 
111 private:
112     void quickSort(vector<int> &worker, int l, int r) {
113         if (l >= r) return;
114         int pivot = patition(worker, l, r);
115         quickSort(worker, l, pivot - 1);
116         quickSort(worker, pivot + 1, r);
117     }
118 
119     int patition(vector<int> &worker, int l, int r) {
120         for (int i = l; i < r; ++i) {
121             if (worker[i] < worker[r])
122                 swap(worker[l++], worker[i]);
123         }
124         swap(worker[l], worker[r]);
125         return l;
126     }
127 };
128 冒泡
129 
130 class Solution {
131 public:
132     ListNode* sortList(ListNode* head) {
133         vector<ListNode*> worker;
134         ListNode temp(0), *ptr = head;
135         while (ptr) worker.push_back(ptr), ptr = ptr->next;
136         for (int i = worker.size() - 1; i >= 0; --i) {
137             for (int j = 0; j < i; ++j)
138                 if (worker[j]->val > worker[j + 1]->val)
139                     swap(worker[j], worker[j + 1]);
140         }
141         ptr = &temp;
142         for (auto i : worker) ptr = ptr->next = i;
143         ptr->next = nullptr;
144         return temp.next;
145     }
146 };
147 
148 作者:fengziL
149 链接:https://leetcode-cn.com/problems/sort-list/solution/7fen-ji-jian-cdai-ma-zhi-wei-zheng-li-si-wqr0/
150 来源:力扣(LeetCode)
151 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Code

 

 

 

题目链接:142. 环形链表 II - 力扣(LeetCode) (leetcode-cn.com)

链表嘛,无非就那几种方法,玩不出什么花来,最多双指针或者三指针,差不多了,再难点就是快慢指针。

这道题先判断是否存在环,然后再求环的起点。

是否有环很好判断,难想到的就是求环起点,数学推导如下:

设head到环起点为a,环起点到环里快慢指针相遇点为b,相遇点到环起点为c,(环长b+c)则有

a+b+(b+c)*n = 2*(a+b)

化简得:a = (b+c)*(n-1)+c;

特殊值n=1理解的话,就是快指针只转了一圈多就相遇。此时a = c,意思是慢指针再走c距离到环起点,头指针同时走c距离,刚好也到环起点,相遇即是等式。

 1 class Solution {
 2 public:
 3     ListNode *detectCycle(ListNode *head) {
 4         ListNode * slow = head;
 5         ListNode * fast = head;
 6         while(fast!=nullptr&&fast->next!=nullptr){
 7             fast = fast->next->next;
 8             slow = slow->next;
 9             if(fast == slow){
10                 ListNode * pre = head;
11                 while(pre != slow){
12                     pre = pre->next;
13                     slow = slow->next;
14                 }
15                 return pre ;
16             }
17         }
18         return nullptr;
19     }
20 };
View Code

 

还有,慢指针一定是第一圈还没转完就和快指针相遇了,因为慢指针半圈,快指针转一圈,所以无论快指针在哪,最多慢指针转半圈就相遇了。

 

234. 回文链表 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     bool isPalindrome(ListNode* head) {
 4         if (head == nullptr || head->next == nullptr) return true;
 5         ListNode* slow = head; // 慢指针,找到链表中间分位置,作为分割
 6         ListNode* fast = head;
 7         while (fast && fast->next) {//12的话 ,1  2;123的话,1,23;1234的话,1
 8             slow = slow->next;
 9             fast = fast->next->next;
10         }
11         if(fast)//奇数,1 ,23,23变成3再反转
12             slow = slow->next;
13 
14         ListNode* cur1 = head;  // 前半部分
15         ListNode* cur2 = reverseList(slow); //
16 
17         // 开始两个链表的比较
18         while (cur1&&cur2) {
19             if (cur1->val != cur2->val) return false;
20             cur1 = cur1->next;
21             cur2 = cur2->next;
22         }
23         return true;
24     }
25     // 反转链表
26     ListNode* reverseList(ListNode* head) {
27         ListNode* temp; // 保存cur的下一个节点
28         ListNode* cur = head;
29         ListNode* pre = nullptr;
30         while(cur) {
31             temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
32             cur->next = pre; // 翻转操作
33             // 更新pre 和 cur指针
34             pre = cur;
35             cur = temp;
36         }
37         return pre;
38     }
39 };
View Code

 

posted @ 2022-01-13 19:57  剩下的交给时间就好  阅读(32)  评论(0编辑  收藏  举报