[豪の算法奇妙冒险] 代码随想录算法训练营第四天 | 24-两两交换链表中的节点、19-删除链表的倒数第N个节点、面试题02.07-链表相交、142-环形链表II
代码随想录算法训练营第四天 | 24-两两交换链表中的节点、19-删除链表的倒数第N个节点、面试题02.07-链表相交、142-环形链表II
LeetCode24-两两交换链表中的节点
题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/description/
文章讲解:https://programmercarl.com/0024.两两交换链表中的节点.html
视频讲解:https://www.bilibili.com/video/BV1YT411g7br/?vd_source=b989f2b109eb3b17e8178154a7de7a51
一拿到题目,我的思路是采用虚拟头节点保存Head的初始位置,先单独排除无元素和一个元素的情况,接着再单独处理两个元素的情况,之后如果符合条件再进行循环交换
循环交换的时候,使用pre、cur和after三个指针遍历链表,进行cur和after所指节点的两两交换,关键在于确定何时停止循环和避免操作空指针
总的来说还是要多画图、多分析

class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = head;
if(dummyHead == null || dummyHead.next == null){
return dummyHead;
}
ListNode pre = null;
ListNode cur = dummyHead;
ListNode after = dummyHead.next;
cur.next = after.next;
after.next = cur;
dummyHead = after;
pre = cur;
cur = cur.next;
while(cur != null){
after = cur.next;
if(after == null){
break;
}
pre.next = after;
cur.next = after.next;
after.next = cur;
pre = cur;
cur = cur.next;
}
return dummyHead;
}
}
看完Carl哥的讲解后,发现我的这个解法还能再活用dummyHead,进行逻辑的优化,统一操作链表,代码也更加简洁明了

class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = new ListNode();
dummyHead.next = head;
ListNode cur = dummyHead;
while(cur.next != null && cur.next.next != null){
ListNode pre = cur.next;
ListNode after = cur.next.next.next;
cur.next = cur.next.next;
cur.next.next = pre;
pre.next = after;
cur = cur.next.next;
}
return dummyHead.next;
}
}
LeetCode19 删除链表的倒数第N个节点
题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/
文章讲解:https://programmercarl.com/0019.删除链表的倒数第N个节点.html
视频讲解:https://www.bilibili.com/video/BV1vW4y1U7Gf/?vd_source=b989f2b109eb3b17e8178154a7de7a51
采用快慢指针的思想解,快指针从dummyHead出发,先往后移动 n+1 步,然后快慢指针一起往后移动,直到快指针指向null,此时慢指针指向的是要删除的节点的前一个节点

class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyHead = new ListNode();
dummyHead.next = head;
ListNode fast = dummyHead;
ListNode slow = dummyHead;
for(int i = 1;i <= n+1;i++){
fast = fast.next;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummyHead.next;
}
}
面试题02.07 链表相交
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/
拿到题第一眼想到的是双重for循环暴力解,注意单个节点的情况,劈里啪啦写完发现居然能过,但这份代码一点也不优雅,而且时间复杂度来到O(n^2),得改!

public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == headB){
return headA;
}
for(ListNode pA = headA; pA != null; pA = pA.next){
for(ListNode pB = headB; pB != null; pB = pB.next){
if(pA == pB){
return pA;
}
}
}
return null;
}
}
看了题解后自己又写了一遍,大开眼界:可以先求出AB两个链表的长度,然后求出两个链表长度差值,让两个链表的末尾对齐,curA和curB对齐相对短的那一个,然后比较curA和curB是否相同,不同则同时往后移动curA和curB,如果遇到相同的情况则找到了交点,否则返回null。妙呀妙呀!

public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lengthA = 1;
int lengthB = 1;
while(curA != null){
curA = curA.next;
lengthA++;
}
while(curB != null){
curB = curB.next;
lengthB++;
}
curA = headA;
curB = headB;
if(lengthA >= lengthB){
for(int i = 1;i <= lengthA - lengthB;i++){
curA = curA.next;
}
}else{
for(int i = 1;i <= lengthB - lengthA;i++){
curB = curB.next;
}
}
while(curA != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
LeetCode142 环形链表II
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/
文章讲解:https://programmercarl.com/0142.环形链表II.html
视频讲解:https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=b989f2b109eb3b17e8178154a7de7a51
这题解法相当的妙呀,先定义一个快指针和一个慢指针,快指针每次往后走两个节点,慢指针每次往后走一个节点,它们如果相遇则说明链表存在环
接着,由数学推理可以得出,从head到环入口的距离 = (n-1)圈环的距离 + 快慢指针相遇点到环入口的距离
由此可以再定义index1从快慢指针相遇点出发,index2从head出发,它们都每次往后走一个节点,这样index1和index2相遇的节点即为环的入口节点

public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null && fast.next.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;
}
}

浙公网安备 33010602011771号