代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II
24. 两两交换链表中的节点
用虚拟头结点,这样会方便很多。
本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。
看到题目的第一想法:
设置两个节点pre,和cur,初始时均置于虚拟头节点。然后就是移动pre和cur,自己手动画图,看如何才能进行两个节点之间的翻转了。
之后记得把cur节点置于pre处。
package com.second.day4;
public class SwapPairs_24 {
public ListNode swapPairs(ListNode head) {
if(head == null)
return null;
ListNode preHead = new ListNode(0); //虚拟头节点
preHead.next = head;
ListNode pre = preHead;
ListNode cur = preHead;
while(cur.next != null && cur.next.next != null) {
ListNode temp1 = pre; //暂存pre节点
pre = cur.next; //pre和cur均往后移动一位
cur = cur.next.next;
ListNode temp2 = cur.next; //暂存cur的下一位
//交换pre和cur指向的节点
temp1.next = cur;
cur.next = pre;
pre.next = temp2;
//交换后将cur指向pre
cur = pre;
}
return preHead.next;
}
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
node1.next = node2;
node2.next = node3;
node3.next = node4;
SwapPairs_24 demo = new SwapPairs_24();
demo.swapPairs(node1);
}
}
看完代码随想录之后的想法:
思路是一样的,嘻嘻。
自己实现过程中遇到哪些困难:
一定要画图,不然很容易搞不清楚,之后稍微debug后过的。
19.删除链表的倒数第N个节点
双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点,建议先看视频。
看到题目的第一想法:
1.先遍历一遍链表,求出其长度
2.算出链表删除的第几个节点
3.删除节点
package com.second.day4;
public class RemoveNthFromEnd_19 {
public ListNode removeNthFromEnd(ListNode head, int n) {
//先遍历一遍链表,求出其长度
ListNode cur = head;
int length = 0;
while(cur != null) {
length += 1;
cur = cur.next;
}
ListNode preHead = new ListNode(0);
preHead.next = head;
ListNode pre = preHead;
cur = head;
//算出链表删除的第几个节点
length -= n;
while(length > 0) {
pre = cur;
cur = cur.next;
length -= 1;
}
//删除cur节点
pre.next = cur.next;
return preHead.next;
}
}
看完代码随想录之后的想法:
卡哥的思路比我好,设置快慢指针,快指针先走n+1步,然后slow和fast指针再一起走,直到fast指针为空,删除slow后面那个节点。
为什么要fast先走n+1,而不是n呢?因为fast多走一步,结束循环时,slow指针指向删除节点的前一个节点。
比我的想法妙多了。
自己实现过程中遇到哪些困难:
无,嘻嘻。
面试题 02.07. 链表相交
本题没有视频讲解,大家注意 数值相同,不代表指针相同。
看到题目的第一想法:
1.遍历链表a,求其长度
2.遍历链表b,求其长度
3.求其长度差值diff
5.先让长链表先走diff
6.然后同时走,遇到相遇点。
package com.second.day4;
public class GetIntersectionNode_0207 {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null)
return null;
//遍历链表a,求其长度
int length_A = 0;
ListNode curA = headA;
while(curA != null) {
length_A += 1;
curA = curA.next;
}
//遍历链表b,求其长度
int length_B = 0;
ListNode curB = headB;
while(curB != null) {
length_B += 1;
curB = curB.next;
}
int diff = Math.abs(length_A - length_B);
return length_A - length_B > 0 ? IntersectionNode(headA, headB, diff) : IntersectionNode(headB, headA, diff);
}
public ListNode IntersectionNode(ListNode headA, ListNode headB, int diff) {
ListNode curA = headA;
while(diff > 0) {
curA = curA.next;
diff -= 1;
}
ListNode curB = headB;
while(curA != null && curB != null) {
if(curA == curB)
return curA;
curA = curA.next;
curB = curB.next;
}
return null;
}
}
看完代码随想录之后的想法:
思路一样!!!nice!!!
自己实现过程中遇到哪些困难:
无
142. 环形链表 II
算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接/文章讲解/视频讲解:
看到题目的第一想法:
看到这个题的时候只知道自己做过,在我看来,这个题更像是数学题,之后看了题解,没有第一次看题解那么难啦。
看完思想后直接AC
package com.second.day4;
public class DetectCycle_142 {
public ListNode detectCycle(ListNode head) {
ListNode preHead = new ListNode(0);
preHead.next = head;
//定义快慢指针
ListNode fast = preHead;
ListNode slow = preHead;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
//当快慢指针相遇
if(fast == slow) {
//慢指针至于head
slow = preHead;
//slow指针和fast每次移动一位,相遇点即为环的入口
while(slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
}
public static void main(String[] args) {
ListNode node3 = new ListNode(3);
ListNode node2 = new ListNode(2);
ListNode node0 = new ListNode(0);
ListNode node4 = new ListNode(-4);
node3.next = node2;
node2.next = node0;
node0.next = node4;
node4.next = node2;
DetectCycle_142 demo = new DetectCycle_142();
demo.detectCycle(node3);
}
}
看完代码随想录之后的想法:
卡哥真的妙!!!
自己实现过程中遇到哪些困难:
还需努力!!!
今日收获,记录一下自己的学习时长:
今天写了四个题:
24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II
代码:1.5h
博客:1h
不积跬步无以至千里,不积小流无以成江海。继续努力。