当前位置:   article > 正文

代码随想录LeetCode | 链表刷题总结II

代码随想录LeetCode | 链表刷题总结II

前沿:撰写博客的目的是为了再刷时回顾进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。

预:看到题目后的思路和实现的代码。

见:参考答案展示。

感思:对比答案后的思考,与之前做过的题目是否有关联。

行:

(1)对于没做出来的题目,阅读答案后重新做一遍;

(2)下次做题可以尝试改善的方向;

(3)有助于理解的相关的题目

1.两两交换链表中的节点

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

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

输入:head = [1,2,3,4]
输出:[2,1,4,3]

提示:

  • 链表中节点的数目在范围 [0, 100] 内
  • 0 <= Node.val <= 100

一刷时在画布上乱花半小时,始终没有写出答案,二刷能够画出来了,有进步!

推荐在线画布:Excalidraw | Hand-drawn look & feel • Collaborative • SecureExcalidraw | Hand-drawn look & feel • Collaborative • SecureExcalidraw | Hand-drawn look & feel • Collaborative • Secure

  1. class Solution {
  2. //17min
  3. public ListNode swapPairs(ListNode head) {
  4. if(head == null || head.next == null){
  5. return head;
  6. }
  7. ListNode dummyNode = new ListNode();
  8. dummyNode.next = head;
  9. ListNode pre = dummyNode;
  10. ListNode cur = head;
  11. ListNode next = cur.next;
  12. while(next != null){
  13. pre.next = next;
  14. cur.next = next.next;
  15. next.next = cur;
  16. if(cur.next != null && cur.next.next != null){
  17. pre = cur;
  18. cur = cur.next;
  19. next = cur.next;
  20. }else{
  21. next = null;
  22. }
  23. }
  24. return dummyNode.next;
  25. }
  26. }

感思

解题思路:

1.获得想要修改的节点的前节点才能修改(画图确定修改顺序)

2.分奇偶两种情况,判断条件:cur.next != null && cur.next.next !=null

常见错误:空指针or无限循环

画图确定修改顺序:

可行性分析:每次修改next后要删掉原来的指向,可尝试调换顺序来是否可行。

  

2.删除链表的倒数第 N 个结点

题目链接:19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

解题思路:

看到倒数第N个节点,就想到使用快慢指针产生间距N。

只要fast遍历到头,slow即是倒数第N个节点。

  1. // Java代码
  2. class Solution {
  3. public ListNode removeNthFromEnd(ListNode head, int n) {
  4. ListNode dummyNode = new ListNode();
  5. dummyNode.next = head;
  6. ListNode fast = head;
  7. ListNode slow = dummyNode;
  8. for(int i = 1;i < n;i++){
  9. fast = fast.next;
  10. }
  11. while(fast.next != null){
  12. slow = slow.next;
  13. fast = fast.next;
  14. }
  15. slow.next = slow.next.next;
  16. return dummyNode.next;
  17. }
  18. }

见:递归版本有空再实现

  1. // 参考答案:递归版本
  2. class Solution {
  3. public ListNode swapPairs(ListNode head) {
  4. // base case 退出提交
  5. if(head == null || head.next == null) return head;
  6. // 获取当前节点的下一个节点
  7. ListNode next = head.next;
  8. // 进行递归
  9. ListNode newNode = swapPairs(next.next);
  10. // 这里进行交换
  11. next.next = head;
  12. head.next = newNode;
  13. return next;
  14. }
  15. }

3.链表相交

题目链接:面试题 02.07. 链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

预见

大体思路一致,但直接判断值相等,导致共同链前面巧合相同这种情况无法判断

就像例子中会直接将3作为相交节点。

感思

解题思路:相交后必全部相同

1.分别通过while循环,获得两个ListNode的长度Alen,Blen=5,6;

2.长的链表遍历到与短的链表长度相同

3.存储此时经过处理后长度相同的一个链表,命名为temp

4.while循环判断链表是否相同,而不是判断值相等

  1. // Java代码
  2. public class Solution {
  3. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  4. // System.out.println(0);
  5. if(headA == null || headB == null){
  6. return null;
  7. }
  8. ListNode curA = headA;
  9. ListNode curB = headB;
  10. // 1.分别通过while循环,获得两个ListNode的长度Alen,Blen=5,6;
  11. int Alen = 0;
  12. int Blen = 0;
  13. while(curA != null){
  14. curA = curA.next;
  15. Alen++;
  16. }
  17. while(curB != null){
  18. curB = curB.next;
  19. Blen++;
  20. }
  21. // 2.长的链表遍历到与短的链表长度相同
  22. curA = headA;
  23. curB = headB;
  24. int index = 0;
  25. if(Alen > Blen){
  26. for(int i = 0;i < (Alen-Blen);i++){
  27. curA = curA.next;
  28. }
  29. }else{
  30. for(int i = 0;i < (Blen-Alen);i++){
  31. curB = curB.next;
  32. }
  33. }
  34. // 3.存储此时经过处理后长度相同的一个链表,命名为temp
  35. // 4.while循环判断是否存在后半段一直相同的情况,并记录后半段一直相同的长度。
  36. ListNode temp = curA;
  37. while(curA != null){
  38. if(curA == curB){
  39. return curA;
  40. }
  41. curA = curA.next;
  42. curB = curB.next;
  43. }
  44. return null;
  45. }
  46. }

1.环形链表 II

题目链接:142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

做题思路

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. //快慢指针判断有环+数学推导从头遍历获得入环节点;
  4. if(head == null || head.next == null) return null; //head为空肯定不是环
  5. //fast的步频是slow的两倍,所以第一步应该直接等于head.next.next,所以先前要先判断是否能够赋值,即判断head.next是否为空;
  6. //fast和slow的初始化为第一步,便于后面直接写while循环判断,不考虑如何开始(fast != slow)
  7. ListNode fast = head.next.next;
  8. ListNode slow = head.next;
  9. //判断是否为环
  10. while(fast != null && fast.next != null && fast != slow){
  11. fast = fast.next.next;
  12. slow = slow.next;
  13. }
  14. //为空肯定不是环,排除为空导致出的while循环;
  15. if(fast == null || fast.next == null){
  16. return null;
  17. }
  18. //数学推导公式具体看图
  19. while(head != slow){
  20. head = head.next;
  21. slow = slow.next;
  22. }
  23. return head;
  24. }
  25. }

 刷题回顾

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/561209
推荐阅读
相关标签
  

闽ICP备14008679号