算法笔记(六)——链表

打印 上一主题 下一主题

主题 860|帖子 860|积分 2580

技巧:
  

  • 画图观察指针指向;
  • 添加虚拟头节点;
  • 可以多界说几个节点;
  • 快慢双指针;
    常见操作:
  

  • 界说new head
  • 逆序时,头插
  1. ListNode* newhead = new ListNode(0);
  2. ListNode* cur= head;
  3. ListNode* next = cur->next;
  4. cur->next = head->next;
  5. head->next = cur;
  6. cur = next
复制代码
两数相加

   题目:两数相加
  

思路
   逆序的链表,只需要一个临时变量来记录进位的值,然后我们可以正常按照计算规则逐个相加直至链表竣事
  C++代码
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. *     int val;
  5. *     ListNode *next;
  6. *     ListNode() : val(0), next(nullptr) {}
  7. *     ListNode(int x) : val(x), next(nullptr) {}
  8. *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution
  12. {
  13. public:
  14.     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
  15.     {
  16.         ListNode* newhead = new ListNode(-1);
  17.         ListNode* prev = newhead;
  18.         ListNode* cur1 = l1;
  19.         ListNode* cur2 = l2;
  20.         int t = 0;
  21.         while(cur1 || cur2 || t)
  22.         {
  23.             if(cur1)
  24.             {
  25.                 t += cur1->val;
  26.                 cur1 = cur1->next;
  27.             }
  28.             if(cur2)
  29.             {
  30.                 t += cur2->val;
  31.                 cur2 = cur2->next;
  32.             }
  33.             prev->next = new ListNode(t % 10);
  34.             prev = prev->next;
  35.             t /= 10;
  36.         }
  37.         prev = newhead->next;
  38.         delete newhead;
  39.    
  40.         return prev;
  41.     }
  42. };
复制代码
两两交换链表中的节点

   题目:两两交换链表中的节点
  

思路

循环停止条件


  • 奇节点数,next == NUL
  • 偶节点数,cur == NULL
C++代码
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. *     int val;
  5. *     ListNode *next;
  6. *     ListNode() : val(0), next(nullptr) {}
  7. *     ListNode(int x) : val(x), next(nullptr) {}
  8. *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution
  12. {
  13. public:
  14.     ListNode* swapPairs(ListNode* head)
  15.     {
  16.         if(head == nullptr || head->next == nullptr)
  17.             return head;
  18.         ListNode* newhead=new ListNode();
  19.         newhead->next = head;
  20.         ListNode* prev = newhead;
  21.         ListNode* cur = prev->next, *next = cur->next, *nnext = next->next;
  22.         while(cur && next)
  23.         {
  24.             // 重新连接节点(顺序无所谓)
  25.             prev->next = next;
  26.             next->next = cur;
  27.             cur->next = nnext;
  28.             // 迭代节点(注意顺序)
  29.             prev = cur;
  30.             cur = nnext;
  31.             if(cur) next = cur->next;
  32.             if(next) nnext = next->next;
  33.         }
  34.         prev=newhead->next;
  35.         delete newhead;
  36.         return prev;
  37.     }
  38. };
复制代码
重排链表

   题目:重排链表
  

思路


  • 模仿

    • 找到链表的中心节点; 快慢双指针


    • 逆序后面的链表;头插


    • 归并两个链表;双指针

C++代码
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. *     int val;
  5. *     ListNode *next;
  6. *     ListNode() : val(0), next(nullptr) {}
  7. *     ListNode(int x) : val(x), next(nullptr) {}
  8. *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. /**
  12. * Definition for singly-linked list.
  13. * struct ListNode {
  14. *     int val;
  15. *     ListNode *next;
  16. *     ListNode() : val(0), next(nullptr) {}
  17. *     ListNode(int x) : val(x), next(nullptr) {}
  18. *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  19. * };
  20. */
  21. class Solution
  22. {
  23. public:
  24.     void reorderList(ListNode* head)
  25.     {
  26.         ListNode* slow = head;
  27.         ListNode* fast = head->next;
  28.         while (fast && fast->next)
  29.         {
  30.             slow = slow->next;
  31.             fast = fast->next->next;
  32.         }
  33.         //反转后半段链表
  34.         ListNode* second = reverseList(slow->next);
  35.         slow->next = nullptr;
  36.         ListNode* first = head;
  37.         //交替合并first和second
  38.         while (second)
  39.         {
  40.             ListNode* tmpNode1 = first->next;
  41.             ListNode* tmpNode2 = second->next;
  42.             first->next = second;
  43.             second->next = tmpNode1;
  44.             first = tmpNode1;
  45.             second = tmpNode2;
  46.         }
  47.     }
  48.      ListNode* reverseList(ListNode* head)
  49.      {
  50.         if (head == nullptr) return head;
  51.         
  52.         ListNode* prev = nullptr;
  53.         ListNode* cur = head;
  54.         while (cur)
  55.         {
  56.             ListNode* tmp = cur->next;
  57.             cur->next = prev;
  58.             prev = cur;
  59.             cur = tmp;
  60.         }
  61.         return prev;
  62.     }
  63. };
复制代码
归并 K 个升序链表

   题目:归并 K 个升序链表
  

思路


  • 将每个链表的头节点入小堆,每次从堆顶元素开始链接,逐个将堆顶的最小链表节点链接,并不断向堆中添加后续元素;
C++代码
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. *     int val;
  5. *     ListNode *next;
  6. *     ListNode() : val(0), next(nullptr) {}
  7. *     ListNode(int x) : val(x), next(nullptr) {}
  8. *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution
  12. {
  13. public:
  14.     struct cmp
  15.     {
  16.         bool operator()(const ListNode* l1,const ListNode* l2)
  17.         {
  18.             return l1->val > l2->val;
  19.         }
  20.     };
  21.     ListNode* mergeKLists(vector<ListNode*>& lists)
  22.     {   
  23.         // 小堆
  24.         priority_queue<ListNode*,vector<ListNode*>, cmp> heap;
  25.         // 所有头节点进堆
  26.         for(auto l : lists)
  27.             if(l) heap.push(l);
  28.         // 合并
  29.         ListNode* ret = new ListNode(0);
  30.         ListNode* prev = ret;
  31.         while(!heap.empty())
  32.         {
  33.             ListNode* t = heap.top();
  34.             heap.pop();
  35.             prev->next = t;  
  36.             prev = t;
  37.             if(t->next != nullptr) heap.push(t->next);
  38.         }
  39.         prev = ret->next;
  40.         delete ret;
  41.         return prev;
  42.     }
  43. };
复制代码
K个一组翻转链表

   题目:K 个一组翻转链表
  

思路


  • 计算需要翻转的次数
  • 重复 n 次,长度为 k 的链表的逆序
C++代码
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. *     int val;
  5. *     ListNode *next;
  6. *     ListNode() : val(0), next(nullptr) {}
  7. *     ListNode(int x) : val(x), next(nullptr) {}
  8. *     ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution
  12. {
  13. public:
  14.     ListNode* reverseKGroup(ListNode* head, int k)
  15.     {
  16.         // 统计节点个数
  17.         int n = 0;
  18.         ListNode* cur = head;
  19.         while(cur)
  20.         {
  21.             n++;
  22.             cur = cur->next;
  23.         }
  24.         n /= k;
  25.         // 重复n次长度为k的链表逆序
  26.         ListNode* newhead = new ListNode(0);
  27.         ListNode* prev = newhead;
  28.         cur = head;
  29.         for(int i = 0; i < n; i++)
  30.         {
  31.             ListNode* tmp = cur;
  32.             for(int j = 0; j < k; j++)
  33.             {
  34.                 ListNode* next = cur->next;
  35.                 cur->next = prev->next;
  36.                 prev->next = cur;
  37.                 cur = next;
  38.             }
  39.             prev = tmp;
  40.         }
  41.         prev->next = cur;
  42.         return newhead->next;
  43.     }
  44. };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

何小豆儿在此

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表