代码随想录Day4
题目列表
- 24.两交换链表中的节点(LeetCode)
- 19.删除链表的倒数第N个节点(LeetCode)
- 面试题 02.07. 链表相交(160)(LeetCode)
- 142.环形链表II(LeetCode)
解题过程
24. 两两交换链表中的节点
题目描述
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
解题思路
注意事项
1.明确每一步交换后链表状态
在交换过程中因为cur.next会变,所以容易混淆,此时可以设置临时变量存储涉及到的节点。
可以在每写一个语句,都列出当前链表的状态(cur,cur.next,cur.next.next),帮助理解。
设置了虚拟头节点,循环条件可以简化为 current.next != null ,因为虚拟头节点是自己创建的,一定不为空。
2.循环条件与cur的移动
要注意题目要求是两两交换。
代码展示
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode cur = dummy; //0
while(cur.next != null && cur.next.next != null){
ListNode first = cur.next; //1
ListNode second = cur.next.next; //2
ListNode third = cur.next.next.next; //3
//开始时,0->1->2->3
cur.next = second; // 0->2->3 1->2 | first = 1
second.next = first; // 0->2->1 1->2 | first = 1 third = 3
first.next = third; // 0->2->1->3
cur = cur.next.next;
}
return dummy.next;
}
}
19.删除链表的倒数第N个节点
题目描述
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
解题思路
- 如果只用一个循环,考虑到双指针,快慢指针都指向最开始的节点,快指针移动 n 次,此时从“快指针指向节点”数到“满指针指向节点”就有 n+1 个,然后两个指针同时移动直到快指针指向链表最后一个有效节点,此时慢指针指向就是倒数第 n 个节点的前一个(也就是倒数第 n + 1 个)。
- 因为删除是需要知道前一个节点的,所以这样刚好便于操作。
- 考虑到链表只有一个结点的情况,引入虚拟头节点统一操作。
代码展示
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
while(fast.next != null && n > 0 ){
fast = fast.next;
n--;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
链表相交(160)
题目描述
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
解题思路
看了评论区版本2的大神题解,核心在寻找不变量,假设两个链表有交点,它们相交部分有 z 个节点,链表1在交点前有 x 个节点,链表2在交点前有 y 个节点,应该如何定位交点:
- 在x == y 的情况下,两指针移动x次就能找到相等的节点并返回。
- 在x != y 的情况下,两个指针分别遍历两个链表,一直到短的那个遍历结束也不会相等。那如何才能保证它们移动相同次数之后刚好两指针指向交点:
指针 a 遍历链表1移动了 x + z,再从链表2的头节点移动 y 次到相交节点,一共移动 x + z + y;
指针 b 遍历链表2至末尾移动了 y + z, 再从链表1的头节点移动 x 次到相交节点,一共移动 y + z + x;
a 和 b 在移动相同次数(x+y+z)的情况下找到了相交节点。 - 考虑到无交点的情况,可以让指针移动到 null 再跳到另一个链表,经历以上过程在null相遇,最后返回null。
代码展示
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA;
ListNode b = headB;
while(a != b){
if(a == null){
a = headB;
}else{
a = a.next;
}
if(b == null){
b = headA;
}else{
b = b.next;
}
}
return a;
}
}
142.环形链表II
题目描述
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
解题思路
芝士在尽力理解题解罢了(
https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF
代码展示
/**
* 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 fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
ListNode index1 = head;
ListNode index2 = fast;
while(index1 != index2){
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}

浙公网安备 33010602011771号