• 206.反转链表


     <循环不变式的思想>

    题目描述


    反转一个单链表。

    示例:

    输入: 1->2->3->4->5->NULL
    输出: 5->4->3->2->1->NULL

    进阶:
    你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

     

    我的思路  - 迭代


    class Solution:
        def reverseList(self, head: ListNode) -> ListNode:
            pre = None
            while head:
                t= head.next
                head.next = pre
                pre = head
                head = t
            return pre
    • 算法: 

    1. 遍历head结点,用 pre 标记 head 之前的结点,用 t 标记 head 之后的结点。

    2. head 结点 指向 pre 结点
    3. 继续下一个循环

    我的思路 - 递归(误)


    class Solution:
        def reverseList(self, head: ListNode) -> ListNode:
            if not head.next:
                return head
            ans = self.reverseList(head.next)
            # 回溯的时候head从5回到1,这时用ans来指向它(误)
            ans.next = head 
            return ans
    • 算法:

    1. 递归到底,返回尾结点
    2. 回溯的时候用ans指向当前栈帧的结点
    • 存在的问题:

      • 回溯的时候反转结点,这个思路可能导致最后return的是反转后的链表的尾结点(这里return ans就不会出现这个问题了)
      • 最致命的一点:ans是递归到底得到的结果,回溯的时候把 ans 递给上一层,所以 ans 在这里是不会变的。那么什么时候会导致return的结果变化呢?参考这篇文章

         

     题解 - 递归


    class Solution(object):
        def reverseList(self, head):
            if not head.next:
                return head
            ans = self.reverseList(head.next)
            # 回溯的时候当前栈帧的结点是head,我们把head的下一个结点指向当前的head
            head.next.next = head
            head.next = None
            return ans
    •  算法:

      • 结合上面【我的思路】来看

    总结


    • 如何用循环不变式来思考?

      • 考虑初始状态:比如设置虚拟头节点、确定第一次循环从哪个结点开始、等等
      • 考虑保持状态(循环中):我们假设循环到结点P,且P之前的结点已经达到目的,专注于当前结点P该用什么样的算法。
      • 考虑终止状态:主要是防止越界。。
  • 相关阅读:
    抓包的原理
    在ASP.NET MVC中使用JQ插件datatable
    如何禁用Visual Studio 2013的Browser Link功能
    SVN中tag branch trunk用法详解
    ASP.NET MVC和jQuery DataTable整合
    随便看的
    SQL查询今天、昨天、7天内、30天
    在DataTable数据类型最后增加一列,列名为“Column”,内容都为“AAA”
    validform表单验证插件最终版
    context.Session[“xxx”]详解
  • 原文地址:https://www.cnblogs.com/remly/p/11406425.html
Copyright © 2020-2023  润新知