题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/
搞清楚两个结点交换的过程,temp应该存哪个结点的值。
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html#%E6%80%9D%E8%B7%AF
1.没有用head结点,导致转换指针经常进入死胡同。
2.指针交换顺序错误。对于这方面应该多找题看看。
3.temp值存错。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyhead=new ListNode(0,head);
ListNode cur=dummyhead;
while(cur.next!=null && cur.next.next!=null){
ListNode temp=head.next.next;
cur.next=head.next;
head.next.next=head;
head.next=temp;
cur=head;
head=head.next;
}
return dummyhead.next;
}
}
题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
如何找到倒数第N个结点。
1.令快慢指针同时指向虚拟头结点。
2.快指针先移动n步,然后快慢指针同时移动。这样,当快指针指向链表末尾null时,慢指针和快指针差n,就找到了倒数第n个结点。
3.关键是,删除结点需要获取要删除结点的前一个结点。所以,让快指针先走n+1步,这样,当快指针指向null时,慢指针刚好指向要删除结点的前一个结点。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyhead=new ListNode(0,head);
ListNode slow=dummyhead;
ListNode fast=dummyhead;
for(int i=0;i
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/
注意,要找的是链表相交的指针,而不是值。题目中为方便理解,把相交结点的值也设为相同。但实际上找的是相交的指针。这也是为什么在if判断语句中直接判断的是cura==curb。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lena=0;
int lenb=0;
ListNode cura=headA;
ListNode curb=headB;
//获取A链表长度
while(cura!=null){
lena++;
cura=cura.next;
}
//获取B链表长度
while(curb!=null){
lenb++;
curb=curb.next;
}
cura=headA;
curb=headB;
//指定A链表为较长的那个
if(lenb>lena){
//交换链表长度
int temp=lenb;
lenb=lena;
lena=temp;
//交换两个链表的指向头结点的指针
ListNode tempnode=cura;
cura=curb;
curb=tempnode;
}
//把两条链表的末端对齐
int gap=lena-lenb;
while(gap-->0){
cura=cura.next;
}
while(cura!=null){
if(cura==curb){
return cura;
}
cura=cura.next;
curb=curb.next;
}
return null;
}
}
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/
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;
}
}
1.如何判断是否有环?
定义快慢指针。快指针一次走两格,慢指针一次走一格。
无环时,快慢指针永远无法相遇。反之,则会相遇。
2.有环为什么快指针一定会和慢指针相遇而不会错过?
快指针一定比慢指针先入环,快指针相对于慢指针来说一次相当于走一格。所以快慢指针一定会相遇。
如图所示。
相遇时慢指针走过的路程:x+y
相遇时快指针走过的路程:x+y+n(y+z),n>=1
x+y=x+y+n(y+z),求得x=(n-1)(y+z)+z.
1.n为什么大于等于1?
n>=1的意思是相遇时快指针已经走了不止一圈。想象以下,快慢指针相遇必须是快指针去追慢指针,因此一定不会在第一圈就追上。
2.为什么慢指针走过的路程不是x+y+k(y+z)?
如图所示。将一圈拉成一条线段。快指针一定先进入环,当慢指针在入口处时,假设想要走一圈即走到下一个入口,那么快指针走的路程是慢指针的两倍,所以一定会在慢指针到达下一个入口前和它相遇。
这道题的数学思路让我感到很奇妙,将圈转换成线段,用变量来证明,值得我反复复习思考。
让解题以统一的写法写出,省时省事。
增删改查
和数组的交换有些相似,但要注意要让交换结点的上一个结点指向交换后的结点。例如,需要交换第三个和第四个结点,那么需要将第二个结点指向反转过来的原第四个结点。
需要注意的是链表相交的结点是内存地址相同的结点。
如何利用快慢指针判断有环,如何找到环的入口,数学证明和思路值得反复复习。