代码随想录算法训练营day4 | 链表 | 24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 160.链表相交 142.环形链表II

第 章

24. 两两交换链表中的节点

建议:用虚拟头结点,这样会方便很多。
题目链接/文章讲解/视频讲解:文章链接

题目链接leetcode 24
题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
在这里插入图片描述

虚拟头结点

思路:创建虚拟结点,然后进行交换,注意顺序。把节点按顺序用 0 1 2 3 标清楚,在草稿纸上画画就清晰了。

代码:

var swapPairs = function (head) {
    let ret = new ListNode(0, head)   // 创建虚拟结点
    let node = ret
    while (node.next != null && node.next.next != null) {
        let p = node.next
        let q = p.next
        p.next = q.next  //1-3
        q.next = p    //2-1
        node.next = q    //0-2
        node = p   // 0到2,开始下一轮
    }
    return ret.next
};

总结

时间复杂度:O(n)
空间复杂度:O(1)
这个真的很容易写错,就是谁先谁后,画画图就清楚多了。

 		node.next=q
        q.next=p
        p.next=q.next
        // 一不小心写了个循环,得注意一下哈哈

19.删除链表的倒数第N个节点

建议:双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点,建议先看视频。
题目链接/文章讲解/视频讲解:文章链接

题目链接leetcode 19
题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
在这里插入图片描述

快慢指针

思路:让快指针先走n步,然后快慢指针一起走,当快指针走到最后一个结点的时候,慢指针刚好指向的是要删除结点的前一个结点。另外使用虚拟头结点可以很好地解决第一个结点的情况。

代码:

/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
    let ret = new  ListNode(0,head)
    let slow = fast = ret
    while(n--) fast = fast.next
    while(fast.next){
        slow=slow.next
        fast=fast.next
    }
    slow.next = slow.next.next
    return ret.next
};

时间复杂度 O ( n ) O(n) O(n)
空间复杂度 O ( 1 ) O(1) O(1)

总结

这道题注意一下:while(fast.next)我在while循环中就直接判断了,如果fast.next为空就不继续进行了,所以说,刚好slow指向的就是待删除结点的前一个结点。

面试题 02.07. 链表相交

建议:注意 数值相同,不代表指针相同。
题目链接/文章讲解/视频讲解:文章链接

题目链接链表相交
题目描述:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:
在这里插入图片描述

暴力法

思路:拿到题就是想到的是暴力法,但是这个题,我看的真的很懵逼,第一个里面的1不相等下面的2又相等。实在是不明白,去看了视频。数值相同,不代表指针相同,这个我去理解了一下——题目的意思是让你找公共结点,**两个链表中有些结点是共用的,也就是地址一样,**让你找出共用的第一个结点。看到这句话明白了,也就是说,虽然例子1的值相等,但是1结点不是共用的!所以说值相等但是不一定是相交结点。
既然是地址相等,让两个链表末位对齐,那么如果有两个对齐的值相等,就能找到公共结点。

代码:

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
//  求链表长度
var getListLen = function(head) {
    let len = 0, cur = head;
    while(cur) {
       len++;
       cur = cur.next;
    }
    return len;
}
var getIntersectionNode = function(headA, headB) {
    let curA = headA,curB = headB,
        lenA = getListLen(headA),   // 求链表A的长度
        lenB = getListLen(headB);  
    if(lenA < lenB) {       // 让curA为最长链表的头,lenA为其长度
    
        // 交换变量注意加 “分号” ,两个数组交换变量在同一个作用域下时
        // 如果不加分号,下面两条代码等同于一条代码: [curA, curB] = [lenB, lenA]
        
        [curA, curB] = [curB, curA];
        [lenA, lenB] = [lenB, lenA];
    }
    let i = lenA - lenB;   // 求长度差
    while(i-- > 0) {       // 让curA和curB在同一起点上(末尾位置对齐)
        curA = curA.next;
    }
    while(curA && curA !== curB) {  // 遍历curA 和 curB,遇到相同则直接返回
        curA = curA.next;
        curB = curB.next;
    }
    return curA;
};

总结

这个题理解起来有点绕,在思路里全部都已经进行了展现
时间复杂度:O(n + m)
空间复杂度:O(1)

142.环形链表II (待补充)

建议:算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。
题目链接/文章讲解/视频讲解:文章链接

题目链接leetcode 142
题目描述:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

方法一

思路:怎么确定题目中有环?

代码:


总结

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值