代码随想录算法训练营第四天|24,19,160,142

前一天学习了链表的数据结构 ,题目都是使用的单链结构, 今天接触了一下更复杂的链表结构。 

24. Swap Nodes in Pairs (Medium)

思路: 交换第 i, i+1 个节点需要 1. 第 i 个节点的指针指向 i+2,2, i + 1 指针指向 i  3. i - 1 指向 i + 1。 4.  当前处理的节点从 i 移到 i + 2, 前一个节点从 i - 1 移动到交换之后的 i。

难点: 注意由于需要处理 i - 1. 可以在head 前面再添加一个节点。 注意while loop 跳出条件。  

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        new_head = ListNode(0, head)
        prev_node = new_head
        while head and head.next:
            next_node = head.next
            tmp_node = next_node.next
            head.next = tmp_node
            next_node.next = head
            prev_node.next = next_node
            # update position
            prev_node = head
            head = tmp_node
        return new_head.next

19. Remove Nth Node From End of List

思路:最容易想到的是先计算链表的长度 l, 然后删除第 l - n + 1 个节点。 题目提示可以用一次循环, 那么可以用到双指针, 先让快指针走n 步, 然后快慢指针同步往前走知道快指针走到头儿,慢指针指向的下一个节点就是要删除的节点。 有点像slicing window 那样操作。

难点:head 前增加新的 node 来一般化删除head 的特殊情况。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        new_head = ListNode(0, head)
        fast_node = new_head
        slow_node = new_head
        i = 0
        while fast_node and i<n:
            fast_node = fast_node.next
            i += 1
        while fast_node.next:
            slow_node = slow_node.next
            fast_node = fast_node.next
        # remove slow_node.next
        slow_node.next = slow_node.next.next
        return new_head.next

160. Intersection of Two Linked Lists

思路: 其实和上一个问题类似, A, B 两个链表的指针从 head 往后移动, 直到一个到头。 另一个如果还没有到头, 那说明非相交的部分不一样长。 不是一般性的假设 A 走完了,B 没有走完, 那么 B 的指针和head 同时移动知道 B 到头儿, 这样A 和新的 B 就有一样的长度。 然后 A,B 的head 同时往后走,如果能碰到, 就是交汇点, 如果碰不到, 就是没有交汇点。 

难点: 无

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
        tmp_nodeA, tmp_nodeB = headA, headB
        while tmp_nodeA and tmp_nodeB:
            tmp_nodeA = tmp_nodeA.next
            tmp_nodeB = tmp_nodeB.next
        # if tmp_nodeA is not None, length of LinkedList A is greater than B
        # move head of A forword until tmp_nodeA to None to make A and B have the same length
        while tmp_nodeA:
            headA = headA.next
            tmp_nodeA = tmp_nodeA.next
        while tmp_nodeB:
            headB = headB.next
            tmp_nodeB = tmp_nodeB.next
        # move headA and head B with same speed until they meet each other. 
        while headA and headB:
            if headA == headB:
                return headA
            headA = headA.next
            headB = headB.next
        return None

142. Linked List Cycle II 

142. Linked List Cycle II

思路:之前做过使用memory O(1) 算法判断链表有无循环,直接套圈就行。 但是找到节点难度要高上不少。 需要一些 math 的推算:

假设环的节点有 j个。

快指针走两步, 慢指针走一步, 设快针走x步遇到第一次慢针。

当 x % 2 = 0 时,快针走了x, 慢针走了x/2, 快针比慢针多走了 n * j, n为正整数。

x - \frac{x}{2} = n \times jx = 2nj

此时慢针退回原点,快慢针同时同速度走, 可以满足快慢针再次相遇, 并且正好在入口。

同理,当 x % 2 = 1 时

x - \frac{x-1}{2} = n \times jx+1 = 2nj

此时慢针退回原点,快针前走一步, 然后快慢针同时同速度走, 可以满足快慢针再次相遇, 并且正好在入口。

 难点: 思路就是难点, 实现比较简单

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow_node, fast_node = head, head
        i = 0
        # first check if there is a loop
        while fast_node:
            i += 1
            fast_node = fast_node.next
            if i % 2 == 0:
                slow_node = slow_node.next 
            if slow_node == fast_node: break # there is a loop
        if not fast_node: return None
        # find loop start node
        slow_node = head
        if i % 2 == 1: fast_node = fast_node.next
        while True:
            if fast_node == slow_node: return fast_node
            fast_node = fast_node.next
            slow_node = slow_node.next 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
代码随想录算法训练是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值