代码随想录算法训练营第四天【链表】24.两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07.链表相交、142.环形链表II
24.两两交换链表中的节点
力扣题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/
心得:关键是定义虚拟头结点、理清循环终止条件,交换的顺序,避免出现空指针、死循环。本题看视频理清思路之后,很快做出来了。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode swapPairs(ListNode head) { ListNode dummyHead = new ListNode(); dummyHead.next = head; ListNode cur = dummyHead; ListNode temp1; ListNode temp2; while(cur.next!=null && cur.next.next!=null){ temp1 = cur.next; temp2 = cur.next.next.next; cur.next = cur.next.next; cur.next.next = temp1; temp1.next = temp2; cur = temp1; } return dummyHead.next; } }
19.删除链表的倒数第N个节点
力扣题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/submissions/
心得:关键在于怎么找到“倒数第N个节点的前一个节点”,双指针思想太妙了。
1)分析倒数第N个节点的特征:该节点之后的第N个节点一定为null
2)slow来代表目标节点,fast来代表目标节点后的第N个节点
3)slow的起始位置是虚拟节点,用for循环计算n次,找到fast的初始节点
4)目标节点slow应该是要删除节点的前一个节点,因此fast也是null的前一个节点,所以当fast.next != null时,slow和fast就不断向后移动
5)找到目标节点,自然就可以轻松删除了
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummyHead = new ListNode(); dummyHead.next = head; ListNode slow = dummyHead; ListNode fast = dummyHead; for(int i=0;i<n;i++){ fast = fast.next; } while(fast.next != null){ slow = slow.next; fast = fast.next; } slow.next = slow.next.next; return dummyHead.next; } }
面试题 02.07.链表相交
力扣题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
心得:思考了十分钟没什么思路,果断看题解了。核心思路就是让两个链表末尾对齐!然后从较短的头结点开始遍历比较,匹配到就返回当前节点,到最后也没有相同节点则返回null。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode curA = headA; ListNode curB = headB; int lenA = 0; int lenB = 0; while(curA != null){ curA = curA.next; lenA++; } while(curB != null){ curB = curB.next; lenB++; } int len = 0; ListNode curLong; ListNode curShort; if(lenA > lenB){ curLong = headA; curShort = headB; len = lenA-lenB; }else{ curLong = headB; curShort = headA; len = lenB-lenA; } while(len-- > 0){ curLong = curLong.next; } while(curLong != null){ if(curLong == curShort){ return curLong; } curLong = curLong.next; curShort = curShort.next; } return null; } }
142.环形链表II
力扣题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/submissions/
心得:本题的重点是快慢指针,通过数学公式推导出步长的关系。
1)(x + y) * 2 = x + y + n (y + z) => x = (n - 1) (y + z) + z
2)寻到快慢指针相遇点
3)寻到开始入环的节点
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode detectCycle(ListNode head) { ListNode slow = head; ListNode fast = head; while(fast!=null && fast.next!=null){ fast = fast.next.next; slow = slow.next; if(fast == slow){ ListNode index1 = fast; ListNode index2 = head; while(index1 != index2){ index1 = index1.next; index2 = index2.next; } return index1; } } return null; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?