Leetcode 24, 19,面试题02.07

这篇博客详细介绍了LeetCode中关于链表的四个问题:两两交换链表节点(24),删除链表倒数第N个节点(19),链表相交以及环形链表(142)。通过初始思路、学习过程和实现方法,深入剖析了每个问题的解决策略,强调了画图和指针操作的重要性,并提及了利用栈和哈希的替代解法。文章总结指出链表题的关键在于理解指针动态变化和边界条件处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

Leetcode 24

初始思路

学习后

实现过程

Leetcode 19

初始思路

学习后

实现过程

思路一

思路二

面试题02.07

初始思路

学习后

实现过程:

 Leetcode142

初始思路

学习后

思路一

思路二

总结


Leetcode 24

题目:两两交换链表节点

学习资料:代码随想录

初始思路

  • 首先画图,尝试双指针,发现后续遍历过程中无法将前一个节点链接至现有节点。进而需要3个指针,由于head位置可能特殊,所以引入虚拟节点。
  • 实现过程中,发现指针更新的方式比较蠢

学习后

  • 思路基本一致,主要是更新部分,其实就是每次更新pre指针就好,cur和ne指针都是根据pre指针来定义

实现过程

  • 注意循环终止条件,画图就可以知道,就是cur和ne等于none时就终止,实现上就是pre.next和pre.next.next 不为none
        dummy = ListNode(next=head)
        pre = dummy

        while pre.next and pre.next.next:

            cur = pre.next
            ne = pre.next.next

            cur.next = ne.next
            ne.next = cur
            pre.next = ne

            pre = pre.next.next
        
        return dummy.next

Leetcode 19

题目:删除链表倒数第N个

学习资料:代码随想录

初始思路

  • 两个距离为n的前后指针,其中cur含义为假设当前指针所指位置为最后一个,re指针含义就为倒数第n个节点的前一个节点。
  • 思路有点类似滑动窗口,先确定窗口终止位置cur的位置,然后一起滑动;cur的初始位置就是虚拟节点后第n个节点
  • 根据定义,那么当cur.next 为none时就停止。
  • 考虑头节点的情况,引入虚拟节点

学习后

  • 思路基本一致
  • 学习其他方法后,感觉利用栈的思路也不错,先把所有入栈,然后遍历n次出栈,当前栈顶元素即为要被删除的前一个节点;空间复杂度较高

实现过程

  • 重点要按照自己的定义来思考边界条件,如何处理
  • 使用dummy节点

思路一

        dummy = ListNode(next=head)
        cur = dummy
        re  = dummy
        for _ in range(n):
            cur = cur.next
        
        while cur.next:
            cur = cur.next
            re = re.next
        re.next = re.next.next

思路二

        dummy = ListNode(0, head)
        s = list()
        cur = dummy
        while cur:
            s.append(cur)
            cur = cur.next
        
        for i in range(n):
            s.pop()

        prev = s[-1]
        prev.next = prev.next.next
        return dummy.next

面试题02.07

题目:链表相交

学习资料:代码随想录

初始思路

  • 利用hash存储,空间复杂度较高

学习后

  • 先遍历自身链表,再遍历另一个链表;两个指针同时进行这一个操作,当两个指针相等时,即为相交节点。如果不存在这种情况即公共部分长度为0,则为null
  • 理解如下图,当A遍历后,从B开始到达相交节点所走的距离为:a-c + c; 当B遍历后,从B开始到达相交节点所走的距离为:b-c + c

实现过程:

        A = headA
        B = headB
        while(A!=B):
            A = A.next if A else headB
            B = B.next if B else headA

        return A

 Leetcode142

题目:环形链表

学习资料:代码随想录

初始思路

  • 使用set来记录,如果出现重复即为环入口;存储的是指针而不是val值

学习后

  • fast,slow指针,fast走2步,slow走1步,fast与slow一定在环中相遇。
  • 如何判断环开始位置?
    • 假设x为从头到入环口距离,y为slow从环到相遇点距离,z为从相遇点到入口点距离
    • 那么相遇就有,slow走过的为x+y,fast走过的为n(z+y)+x
    • 那么由于相差两倍,所以 2*(x+y) = n(z+y)+x;x = (n-1)(y+z)+z; n 大于等于1
    • 当n=1时,x=z说明,从头到入口的距离和从相遇点到入口的距离相等。
  • 这个方法需要的推理证明较多,较难理解

思路一

        temp = set()
        p = head
        while p != None:
            if p not in temp:
                temp.add(p)
                p = p.next

            else:
                return p
        return None

思路二

        slow = head
        fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next

            if slow == fast:
                index1 = head
                index2 = slow
                while index1 != index2:
                    index1 = index1.next
                    index2 = index2.next
                return index1
        return None

总结

  • 重点为前两个题,后两个题有很多trick;用hash也不错
  • 链表题一定要手动画图,还原指针变化的过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值