代码随想录算法训练营第四天
代码随想录算法训练营第四天 | LeetCode 24(两两交换链表中的节点) LeetCode 19(删除链表的倒数第N个节点) LeetCode 160(链表相交) LeetCode 142(环形链表II)
24:两两交换链表中的节点
这道题其实很简单
画图模拟出是如何交换链表的就好了
要注意的是 这里的交换是 0和1交换 2和三交换以此类推
方法一
class Solution {
public ListNode swapPairs(ListNode head) {
if(null == head || null == head.next){
return head;
}
//设置虚拟头节点
ListNode newNode = new ListNode(-1,head);
//当前节点
ListNode cur = newNode;
//第一节点
ListNode first;
ListNode second;
//临时节点 保存从一,二节点后的第三节点
ListNode temp;
//开始遍历链表 一次查看两个节点
while(null != cur.next && null != cur.next.next){
//先赋值
first = cur.next;
second = cur.next.next;
temp = cur.next.next.next;
//节点交换 当前节点情况 cur first second temp
cur.next = second;
second.next = first;
first.next = temp;
//cur指针移动 当前节点情况 cur second first temp
//因为temp是下一组要交换的节点组中的第一个节点
//那么cur应该指向 temp的前驱节点first
cur = first;
}
return newNode.next;
}
}
19:删除链表的倒数第N个节点
双指针法
使得两个指针距离为n-1 那么当前指针遍历到链表末尾的时候 后指针就是倒数第n个节点啦
方法一
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//定义虚拟头节点
ListNode newNode = new ListNode(-1,head);
ListNode prev = head;
ListNode cur = newNode;
//位移前驱指针
//使得prev和cur相距 n-1 因为倒数的是从1开始计数
n = n - 1;
while(n-- > 0){
prev = prev.next;
}
//使prev遍历到链表结尾 cur也要跟着移动
while(null != prev.next){
prev = prev.next;
cur = cur.next;
}
//删除节点
cur.next = cur.next.next;
return newNode.next;
}
}
160:链表相交
假定a,b成环 当 a,b为null时跳至另一链表起点继续遍历一次
若 a:[4,1,8,4,5] b:[5,0,1,8,4,5]
4 1 (8 4 5) null 5 0 1 (8 4 5) null
a b
方法一
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB)
{
if(headA == null || headB == null){
return null;
}
//假定A B成环 但实际上不是一个环
ListNode a = headA;
ListNode b = headB;
//不会造成死循环 因为若链表不相交 到最后 a,b就会均为null
while(a != b){
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
return a;
}
}
142:环形链表II
快慢指针
fast 一次位移两步
slow 一次位移一步
如果有环 则fast和slow必定会相遇
那么如何找到环的入口呢?
假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z
那么相遇时:
slow指针走过的节点数为: x + y,
fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。
因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:
(x + y) * 2 = x + y + n (y + z)
两边消掉一个(x+y): x + y = n (y + z)
因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。
所以要求x ,将x单独放在左面:x = n (y + z) - y ,
再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针
当 n为1的时候,公式就化解为 x = z,
这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
方法一
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
//结尾有环的话 那么fast.next就不可能遇到null值
while (fast != null && fast.next != null) {
//慢指针一次走一步
slow = slow.next;
//快指针一次走两步
fast = fast.next.next;
//有环
if (slow == fast) {
ListNode a = fast;
ListNode b = head;
// a,b两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
while (a != b) {
a = a.next;
b = b.next;
}
return a;
}
}
return null;
}
}
本文作者:昼阳Helios
本文链接:https://www.cnblogs.com/Q316/p/17692327.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步