有hr说什么现在软件谁还用c++,都是rust了
虽然但是他也太以偏概全了,,((烧饼吧
1. 两两交换链表中的节点
思路:将链表中相邻的节点两两交换,则交换的步骤是
eg:[0] -> [1] -> [2] -> [3] -> [4] 交换1和2,3和4;
则交换的步骤是,先让0指向2,再让2指向1,最后让1指向3,即完成了一次交换;
此时需要注意的细节:
1. 每次交换一对节点的时候,此时的cur指针应该指向当前这对节点的前一个;因为上述交换过程也说了要涉及到0和3嘛
所以!也是区分是不是头节点的!如果是头节点,则先temp = head; tmp1 = head->next->next; head = head->next; head->next = temp; head->next->next = tmp1; 如果是中间节点,则还会有个cur指针,所以操作稍微有点不同,此时为了统一操作,依旧使用虚拟头节点dummyhead。
2. 循环结束的判断!当链表节点为偶数时,每一对节点都会发生交换,cur从一开始指向dummyhead后移到指向最后一个节点,此时cur->next = NULL; 若为奇,则最后一个节点会单独出来,不进行交换,此时cur最后会指向倒数第二个节点,所以cur->next->next = NULL; 所以当他们其中一个为空时,则循环结束。
这里就体现了dummyhead的好处!因为当链表为空时,同样也是判断dummyhead->next != NULL, 如果不用虚拟头节点就要在上述的两个判断中再在一开始加入一个判断head是否为NULL
注意! while中循环的判断顺序不能换;若先判断后面的条件,如果第一个next是NULL,则会报错说访问了空指针,所以要先判断cur->next;
2. 删除链表的倒数第N个节点
方法一:一般思路
我!终于!自己写了一次代码了!太不容易了啊啊啊啊啊啊啊啊啊虽然只是个很简单的删除元素
我的思路!(一般思路)我要标橙
其实就是先得到链表的大小然后再循环到要删除的节点的前一个,因为知道了大小就可以用size-n来循环得到位置,好的我用count表示了大小!
代码如下:
好的,然后就是答案的方式;
方法二:双指针法
又是双指针!!啊啊啊啊啊啊啊啊啊啊啊啊啊啊
定义一个快指针和一个慢指针,让快指针先走n步,然后再快慢指针一起后移直到快指针->next = NULL, 此时的慢指针是刚好指向目标节点的前一个的! 也可以先让快指针走n+1步,然后快慢指针一起后移直到fast = NULL, 此时的慢指针也是刚好指向目标节点的前一个的; 本质是一样的。(具体位置可以举例来试探)
这样的思路来源是!因为是倒数第n个元素,所以当快指针指向最后一个节点时,此时从后往前数的第n个就是要删除的目标节点,所以只要让快慢指针之间相隔n-1个节点!!慢指针就刚好指向目标节点的前一个节点。所以就有了上述的快慢指针同时移动的过程~
代码如下:
这个双指针法真的要比我上面的循环两次来的快得多!!啊啊啊啊啊啊啊啊啊啊啊啊55555
3. 找出两个链表相交的起始点
思路:先计算出两个链表长度的差n,然后让长的链表的指针移动n次,使长的链表此时的指针与短链表的head对齐;可以不用dummy head了~~
(为什么我就想不到这个方法,我果然还是脑子空空)
代码如下:
老是忘记return可以直接终止函数并返回!!
感觉这个题知道思路之后就好做了,所以没有太多要注意的地方,我用的if里面嵌套while可能不太友好,那就看答案里的ba~用了swap(lenA,lenB);看谁大谁放在前面。
4. 环形链表ll
判断链表中是否有环,且得到环的起点位置索引。
1. 首先判断是否有环;
2. 计算入口节点;
1. 判断是否有环,思路:
此处用到了快慢指针的方式来判断是否有环;
因为可以想象成跑道上的相遇问题;
若两个速度不同的人在环形跑道上跑步,则他们一定会相遇;
且相遇所需时间是跑道长度除以两个人的相对速度;
那可以把链表上的相遇问题看作是离散情况的环;
设快指针每次移动两个节点;
慢指针每次移动一个节点;
相对速度就是一个节点;(也可以理解为快指针以一个节点的相对速度在追慢指针)
(注意因为是离散的情况,所以如果相对速度大于一个节点的话,可能会造成快指针超过慢指针的情况,虽然也是相遇过了,但是就无法第一次准确相遇到同一个节点上)
所以判断链表是否有环就是通过判断快慢指针是否会相遇。
2. 计算入口节点,思路:
设head到环入口的节点为x;
相遇时的位置到入口距离为y;
环剩下距离为z;
则慢指针走过的距离为x+y;
快指针走过的距离为x+n(y+z)+y;n表示快指针多走的圈数;
根据相遇时时间相等可以列出等式
2*(x+y) = x+n(y+z)+y;
移项得x+y = n(y+z)
因为要求的是x所以
x = n(y+z) - y; n≥1;
因为我们要求的x是正数,所以我想知道x和正的数有什么关系而不是-y,所以从前面提出一个y+z
x = (n-1)(y+z)+z;
就可以得到,当n=1时,x最小取z;
这就意味着!!!!
n=1时,设置一个index1指针在相遇点,index2指针在head,两人同时前进,就可以在入口处相遇!!
如果n>1, 则表示index1指针从相遇点开始,除了走最后的z距离,还要再多绕几圈,才能有index2走到入口处,主要是他们此时一定会相遇在入口处。(可以画图理解)
eg:n = 2;
x = z+y+z; 在原来z的基础上,多了一圈y+z;
然后在入口处相遇!
【Ps: 为什么一定在慢指针的第一圈他们就会相遇?】
我觉得可以有两个解释
1)答案中的解释:
当快慢指针同时从环的入口出发,慢指针走一圈的时间,快指针刚好走两圈,所以一定是在慢指针第一圈的时候就会相遇。
所以,当慢指针第一次抵达入口,此时快指针一定已经在环里某处位置了(都不是在入口);而因为快指针是慢指针速度的两倍,所以肯定在慢指针的第一圈就追上了。所以等式就只用x+y,不用带字母k了。
2)自己的解释:
我觉得不确定是第一圈就追上也没事,就把k带进等式嘛
那就是
2*[(x+y)+k(y+z)] = x+n(y+z)+y;
2(x+y) + 2k(y+z) = x+n(y+z)+y;
x+y = (n-2k)(y+z);
x = (n-2k)(y+z) - y;
x = (n-2k-1)(y+z) + z;
这个式子的意思同样还是x等于z的大小再加上有多少圈的距离
所以做法还是一个index1在相遇点,一个index2在head然后同时前进。
只是说如果是真的其他类型的数学问题,就要讨论n和k的取值范围等了。
代码如下:
其实弄明白了思路这个题的代码还是不难的((