24. 两两交换链表中的节点
题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)
思路: 基本的链表操作,注意链表的操作顺序,以及使用temp来存储需要存储的节点。
我的代码:
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy, cur = head;
while (cur != null && cur.next != null) {
ListNode temp = cur.next.next;
pre.next = cur.next;
pre.next.next = cur;
cur.next = temp;
pre = cur;
cur = temp;
}
return dummy.next;
}
}
问题:
总结:
19. 删除链表的倒数第N个节点
题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
思路: 刚开始的思路是先遍历得到链表的长度,然后可以知道需要删除的节点的索引,找到需要删除的节点的前一个节点,做相应操作即可。但是这样比较麻烦。 比较好的方法是通过快慢指针即可确认待删除节点的位置,fast先走n步,紧接着slow和fast同时向前走,每次一步,这样当fast == null时,slow会到达链表长度-n的位置,即倒数第n。为了方便删除,slow需要在删除的节点前一个停下,因此fast需要多走一步。
我的代码:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null) return null;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
while (n-- >= 0) {
fast = fast.next;
}
while (fast != null) {
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
问题: 写双指针解法的时候,把slow和fast初始为head,而不是dummy,这样导致如果要删除的节点是头节点,头节点之前的节点将无法访问到,无法删除。因此slow和fast的初始值要设为虚拟头节点。
总结:
设计删除链表节点的操作时,一定要考考虑到头节点是需要虚拟头节点来删除的!
160. 链表相交
思路:
用两个指针 p1 和 p2 分别在两条链表上前进,我们可以让 p1 遍历完链表 A 之后开始遍历链表 B,让 p2 遍历完链表 B 之后开始遍历链表 A,这样相当于「逻辑上」两条链表接在了一起。如果这样进行拼接,就可以让 p1 和 p2 同时进入公共部分,也就是同时到达相交节点。
我的代码:
class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p1 = headA;
ListNode p2 = headB;
while (p1 != p2) {
p1 = p1 == null ? headB : p1.next;
p2 = p2 == null ? headA : p2.next;
}
return p1;
}
}
问题:
总结:
复习了判断两个链表是否相交。
142.环形链表II
题目链接:142. 环形链表 II - 力扣(LeetCode)
思路: 以前做过,(x + y) * 2 = x + y + n (y + z)想不起来了。关于判断是否成环:fast slow双指针。如果相等,说明成环,通过等式可以推出 x = z, 此时新建一个节点 = head, 和slow/fast一起每次前进一步,会在环的入口相遇。
我的代码:
class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
ListNode p1 = head;
while (p1 != slow) {
slow = slow.next;
p1 = p1.next;
}
return p1;
}
}
return null;
}
}
问题:
- while (fast.next != null && fast.next.next != null) 这一步有问题,fast.next.next = null的情况 fast 是可以前进的,应该改为 while (fast != null && fast.next != null)。
正确代码:
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 p1 = head;
while (p1 != slow) {
slow = slow.next;
p1 = p1.next;
}
return p1;
}
}
return null;
}
}
总结:
复习了判断两个链表是否成环。