记录一下代码随想录,19.删除链表的倒数第N个节点 和 面试题02.07.链表相交 两个题。
删除链表的倒数第N个节点
进阶:你能尝试使用一趟扫描实现吗?
这题涉及到删除头节点,为了方便就采用虚拟头节点来做(基本上都是用虚拟头节点,从而节省对头节点的额外处理)。
想到一趟扫描,就想到了双指针。这里使用一快一慢两个指针:fast、slow。
可以推导,让fast 指针先移动N个节点,之后让fast 和 slow同时移动,直至fast 指向链表尾端的null,那么,此时slow 指向的节点就是倒数第N个节点(要被删除的节点)。
因为删除节点需要依靠该节点的前一个节点,所以实际会让fast 指针先移动 N+1 个节点。此时,fast 循环结束后,slow 的下一个节点就是倒数第N个节点。
代码如下:
ListNode dummyHead = new ListNode(-1, head);
ListNode fast = dummyHead;
ListNode slow = dummyHead;
while (n-- > 0) {
fast = fast.next;
}
fast = fast.next; // 移动N+1 个节点
while (fast != null) { // 循环
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next; // 删除倒数第N个节点
return dummyHead.next;
——————————————————————————————————————————
链表相交
这个题是一个简单题,只需要注意 链表如果有相交,那么他们必定是从某个节点开始一直到尾部节点都一样,相交的节点必定是在短链表中。
接下来只需要模拟就可以了。
先让两个链表尾端对齐。假设长链表长度为 lenA,短链表长度为 lenB。尾端对齐,即让长链表指针向后移动 lenA-lenB 个节点。
然后就是一一比对节点,直至找到一个相交的节点,或者 null。
代码如下:
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0;
int lenB = 0;
while (curA != null) { // 获取链表A的长度
curA = curA.next;
lenA++;
}
while (curB != null) { // 获取链表B的长度
curB = curB.next;
lenB++;
}
curA = headA;
curB = headB;
if (lenB > lenA) {
int len = lenB; // 让 lenA 代表长链表的长度,lenB 代表短链表的长度
lenB = lenA;
lenA = len;
ListNode temp = curB; // 让 curA 指向长链表的头节点,lenB 指向短链表的头节点
curB = curA;
curA = temp;
}
int n = lenA - lenB;
while (n-- > 0) { // 让两个链表的尾端对齐
curA = curA.next;
}
while (curA != null) { // 寻找相交的节点
if (curA == curB)
return curA;
curA = curA.next;
curB = curB.next;
}
return null;