Leetcode 92:反转链表II

解决这道题需要三个步骤:

  1. 找到需要反转的第一个节点。可以通过头节点前进m-1步,找到反转开始的位置。
  2. 将需要反转的部分进行反转。参考Leetcode 206:反转链表
  3. 将反转部分与剩余部分进行链接。其中分为两种情况,m=1与m>1。当m=1时,仅需要将反转部分反转前的头节点的next指向反转部分反转前尾节点的后继,新链表的头节点为反转部分反转前的尾节点。当m>1时,还需要将反转部分反转前头节点的前驱的next指向反转部分反转前的末节点,新链表的头节点仍为原链表的头节点。假设m=2,n=4,其中有以下几个关键节点:

  1. class Solution {
  2. public:
  3. ListNode* reverseBetween(ListNode* head, int m, int n) {
  4. int change_len = n - m + 1; //需要反转的长度
  5. ListNode *pre_head = NULL; //反转部分的前驱节点
  6. ListNode *result = head;
  7. while(head && --m) //移动到反转的开始位置
  8. {
  9. pre_head = head;
  10. head = head->next;
  11. }
  12. ListNode *tmp = head; //反转部分头节点,即反转后的尾节点
  13. ListNode *new_head = NULL;
  14. while(head && change_len) //反转部分链表
  15. {
  16. ListNode *next = head->next;
  17. head->next = new_head;
  18. new_head = head;
  19. head = next;
  20. change_len--;
  21. }
  22. tmp->next = head; //反转后的尾节点链接反转段的后一个节点
  23. if (pre_head) //前驱节点不为空,说明m>1
  24. {
  25. pre_head->next = new_head; //反转部分的前驱节点连接反转后的头节点
  26. }
  27. else
  28. {
  29. result = new_head;
  30. }
  31. return result;
  32. }
  33. };

Leetcode 234:回文链表

回文链表就是说从链表的头节点到尾节点,和从链表的尾节点到头节点遍历得到的结果是相同的。简单的做法是利用栈结构,从链表头节点开始将节点依次压入栈中,再依次弹出并连接得到的链表如果与原链表相同,这个链表就是回文链表。如果要求空间复杂度为O(1), 通过快慢指针确定中点,将链表从中点分为两个链表,反转后半部分链表,比较两个子链表的元素。

  1. class Solution {
  2. public:
  3. bool isPalindrome(ListNode* head) {
  4. if(head == NULL)
  5. return true;
  6. ListNode* fast = head;
  7. ListNode* slow = head;
  8. while(fast->next != NULL && fast->next->next != NULL) //使用快慢指针确定中点,节点数为奇时,指向中点;节点数为偶时,指向中间两个数的前者。
  9. {
  10. fast = fast->next->next;
  11. slow = slow->next;
  12. }
  13. ListNode* head1 = slow->next;
  14. slow->next = NULL; //从中点的后一个节点开始反转链表
  15. while(head1 != NULL)
  16. {
  17. ListNode* next = head1->next;
  18. head1->next = slow;
  19. slow = head1;
  20. head1 = next;
  21. }
  22. head1 = slow;
  23. bool res = true;
  24. while(head1 != NULL && head != NULL)
  25. {
  26. if(head1->val != head->val)
  27. return false;
  28. head1 = head1->next;
  29. head = head ->next;
  30. }
  31. return res;
  32. }
  33. };

Leetcode 142:环形链表II

解决这个问题需要两个步骤:

  1. 使用快慢指针判断链表是否存在环。慢指针在链表中一次走一步,快指针一次走两步,如果链表中存在环,快慢指针总会到达同一个节点meet。

  2. 从链表的头节点head以及meet同时出发,两个指针速度相同,相遇时即为环的起点。

    设绿色部分为a,蓝色部分为b,黄色部分为c。可知快指针走过的路程时慢指针的两倍,即2(a+b)=a+b+c+b,可以得到a=c,所以head节点与meet节点相遇时即为环的起点。

  1. class Solution {
  2. public:
  3. ListNode *detectCycle(ListNode *head) {
  4. ListNode* fast = head;
  5. ListNode* slow = head;
  6. ListNode* meet = NULL;
  7. while(fast)
  8. {
  9. fast = fast->next;
  10. slow = slow->next;
  11. if(!fast)
  12. return NULL;
  13. else
  14. fast = fast->next;
  15. if(fast == slow)
  16. {
  17. meet = fast;
  18. break;
  19. }
  20. }
  21. if (meet == NULL)
  22. return NULL;
  23. while(head && meet)
  24. {
  25. if(head == meet)
  26. return meet;
  27. head = head->next;
  28. meet = meet->next;
  29. }
  30. return NULL;
  31. }
  32. };

Leetcode 138:复制带随机指针的链表

解决这个问题需要三个步骤:

  1. 复制节点,将复制的节点连接到原节点之后,原节点的next连接到复制的节点之后。
  2. 复制随机指针。
  3. 分离节点。

  1. class Solution {
  2. public:
  3. Node* copyRandomList(Node* head)
  4. {
  5. if (!head) return nullptr;
  6. Node* curnode = head;
  7. while (curnode) //遍历原链表复制节点
  8. {
  9. Node* copy = new Node(curnode->val, curnode->next, nullptr);
  10. Node* tmp = curnode->next;
  11. curnode->next = copy;
  12. curnode = tmp;
  13. }
  14. curnode = head;
  15. while (curnode) //遍历链表连接复制节点的随机指针
  16. {
  17. if (curnode->random)
  18. curnode->next->random = curnode->random->next;
  19. curnode = curnode->next->next;
  20. }
  21. curnode = head;
  22. Node* new_head = head->next; //复制节点的头节点
  23. while (curnode->next) //分离节点
  24. {
  25. Node* tmp = curnode->next;
  26. curnode->next = curnode->next->next;
  27. curnode = tmp;
  28. }
  29. return new_head;
  30. }
  31. };

Leetcode 23:合并K个排序链表

解决此题的思路类似于归并排序,对于两个排序列表的合并可以参考Leetcode 21:合并两个有序链表,在对k个排序链表进行合并时,可以通过分治的思想,对k个链表两两进行合并。

  1. class Solution {
  2. public:
  3. ListNode* mergeKLists(vector<ListNode*>& lists) {
  4. if(lists.size() == 0)
  5. return NULL;
  6. if(lists.size() == 1)
  7. return lists[0];
  8. if(lists.size() == 2)
  9. return mergeTwoLists(lists[0],lists[1]);
  10. int size = lists.size();
  11. int mid = size/2;
  12. vector<ListNode*> tmp1;
  13. vector<ListNode*> tmp2;
  14. for(int i = 0;i < mid;i++)
  15. {
  16. tmp1.push_back(lists[i]);
  17. }
  18. for(int i = mid;i < size;i++)
  19. {
  20. tmp2.push_back(lists[i]);
  21. }
  22. ListNode* l1 = mergeKLists(tmp1);
  23. ListNode* l2 = mergeKLists(tmp2);
  24. return mergeTwoLists(l1,l2);
  25. }
  26. ListNode* mergeTwoLists(ListNode* list1,ListNode* list2) //合并两个有序链表
  27. {
  28. ListNode new_head(0);
  29. ListNode* prenode = &new_head;
  30. while(list1&&list2)
  31. {
  32. if(list1->val>list2->val)
  33. {
  34. prenode->next=list2;
  35. list2 = list2->next;
  36. }
  37. else
  38. {
  39. prenode->next = list1;
  40. list1 = list1->next;
  41. }
  42. prenode = prenode->next;
  43. }
  44. if(list1) //如果list1不为空,将剩余节点连接在已合并的链表之后
  45. prenode->next = list1;
  46. if(list2) //list2同理
  47. prenode->next = list2;
  48. return new_head.next;
  49. }
  50. };

链表相关的leetcode重要题目的更多相关文章

  1. [LeetCode] [链表] 相关题目总结

    刷完了LeetCode链表相关的经典题目,总结一下用到的技巧: 技巧 哑节点--哑节点可以将很多特殊case(比如:NULL或者单节点问题)转化为一般case进行统一处理,这样代码实现更加简洁,优雅 ...

  2. 剑指offer题目系列三(链表相关题目)

    本篇延续上一篇剑指offer题目系列二,介绍<剑指offer>第二版中的四个题目:O(1)时间内删除链表结点.链表中倒数第k个结点.反转链表.合并两个排序的链表.同样,这些题目并非严格按照 ...

  3. leetcode上题目的分类

    leetcode链表部分题目 https://zhuanlan.zhihu.com/p/29800285 <[Leetcode][链表]相关题目汇总/分析/总结> leetcode堆部分题 ...

  4. LeetCode高频题目(100)汇总-Java实现

    LeetCode高频题目(100)汇总-Java实现       LeetCode高频题目(100)汇总-Java实现 目录 第01-50题 [Leetcode-easy-1] Two Sum [Le ...

  5. LeetCode算法题目解答汇总(转自四火的唠叨)

    LeetCode算法题目解答汇总 本文转自<四火的唠叨> 只要不是特别忙或者特别不方便,最近一直保持着每天做几道算法题的规律,到后来随着难度的增加,每天做的题目越来越少.我的初衷就是练习, ...

  6. LeetCode SQL题目(第一弹)

    LeetCode SQL题目 注意:Leetcode上的SQL编程题都提供了数据表的架构程序,只需要将它贴入本地数据库即可调试自己编写的程序 不管是MS-SQL Server还是MySQL都需要登陆才 ...

  7. [数据结构]链表相关的实现LinkList.cpp

    目录 LinkList.cpp //链表相关操作的实现 LinkList.h LinkListManager.cpp //链表相关实现函数的调用 LinkListManager.h LinkList. ...

  8. leetcode二叉树题目总结

    leetcode二叉树题目总结 题目链接:https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/ 前序遍历(NLR) p ...

  9. leetcode 单链表相关题目汇总

      leetcode-19-Remove Nth From End of List—移除链表中倒数第n个元素 leetcode-21-Merge Two Sorted Lists—两个已排序链表归并 ...

随机推荐

  1. 用block变量来对字符数组对象进行排序

    <span style="font-size:18px;">降序排序</span> <span style="font-size:18px; ...

  2. JSP内建对象

    ① out - javax.servlet.jsp.jspWriter    out对象用于把结果输出到网页上. 方法: 1. void clear() ;    清除输出缓冲区的内容,可是不输出到c ...

  3. windows下mongodb设置用户名密码&用python连接

    环境: 主机:WIN10 python版本:3.5 mongodb版本:3.4.2 开发环境:pyCharm mongodb设置用户名密码: 编写mongodb配置文件mongodb.confdbpa ...

  4. luogu3942将军令

    https://www.zybuluo.com/ysner/note/1302132 题面 在大小为\(n\)的树上选择尽量少的点,使得所有未选择的点距离选择了的点小于等于\(k\). \(n\leq ...

  5. CF 1042 A Benches —— 二分答案(水题)

    题目:http://codeforces.com/problemset/problem/1042/A 代码如下: #include<iostream> #include<cstdio ...

  6. bzoj1791

    1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1680  Solved: 369[Submit][S ...

  7. RT-Thread 设备驱动-硬件定时器浅析与使用

    RT-Thread 4.0.0 访问硬件定时器设备 应用程序通过 RT-Thread 提供的 I/O 设备管理接口来访问硬件定时器设备,相关接口如下所示: 函数 描述 rt_device_find() ...

  8. linux Java环境变了配置

    1. sudo /etc/profile 2.安装截图配置 输入javac 进行验证

  9. 洛谷P1010 幂次方

    题目描述 任何一个正整数都可以用2的幂次方表示.例如 137=2^7+2^3+2^0 同时约定方次用括号来表示,即a^b 可表示为a(b). 由此可知,137137可表示为: 2(7)+2(3)+2( ...

  10. java io 读取写文件

    java 读取txt文件,汉字乱码,原因是因为文件的编码格式和程序编码采用了不同的编码格式.通常,假如自己不修改的话,windows自身采用的编码格式是gbk(而gbk和gb2312基本上是一样的编码 ...