• 递归:解题思路


    1. 子问题与原问题是否是一致的,子问题是否只是缩小了问题的规模
    2. 如果原问题的解不依赖于子问题的解,这个问题肯定不用递归,否则可以考虑递归
    3. 假设子问题已经解决了,这个时候如何将入参与子问题的解进行逻辑处理,从而得到原问题的解
    4. 链表,数组,二叉树这种结构本身就有递归属性
    1. 列表求和问题
      原问题是从头到位对整个链表求和,子问题本质也是求和,只是问题规模缩小了
      在这里插入图片描述
    2. 汉诺塔问题
      原问题是把N个圆盘由A移动到C,子问题可以变为把N-1个圆盘由A移动到B,然后在把这个N-1个圆盘移动到C。从下图可以看到共调用了两次子问题
      在这里插入图片描述
    class Solution:
        def hanota(self, A: List[int], B: List[int], C: List[int]) -> None:
            """
            Do not return anything, modify C in-place instead.
            """
    
            def move(n,A,B,C): # 原问题
                if n == 1:
                    C.append(A.pop())
                    return
    
                move(n-1, A, C, B) # 子问题
                C.append(A.pop()) # 逻辑
                move(n-1, B, A, C) # 子问题
            
            n = len(A)
            move(n,A,B,C)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 合并两个有序链表
      原问题是合并两个链表,当我们提取出最小值的时候,子问题就可以变成合并缩小规模后的两条链表,例如合并两个链表list1=[1,2,4,8],list2=[2,3,6,7],我们提取出当前最小值是list1的头节点,子问题就变成合并两个链表list1=[2,4,8],list2=[2,3,6,7],然后将list1的头节点拼接上即可
      在这里插入图片描述
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
            if list1 is None:
                return list2
            if list2 is None:
                return list1
            if list1.val <= list2.val:
                list1.next = self.mergeTwoLists(list1.next,list2)
                return list1
            else:
                list2.next = self.mergeTwoLists(list1,list2.next)
                return list2
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    1. 反转链表
      原问题是反转[1,2,2,3,4,6],子问题是反转[2,2,3,4,6],我们把1拼接到后面即可。
      在这里插入图片描述
      这个就是逻辑处理,然后反复调用自身即可
      在这里插入图片描述
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
            if head is None or head.next is None:
                return head
            last = self.reverseList(head.next)
            head.next.next = head
            head.next = None
            return last
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    链表的递归反转最让我难以理解的就是last的返回,我们知道反转之后需要把最后一个元素最为head节点返回的,但是递归通常是返回上一层的节点

    1. 两个数组的交集
      这个问题并不能使用递归解决,但是因为很像递归,我单独分析一下。假如我们子问题已经求出解了,现在的问题是如何把元素1和子问题的解[2,4] 合并到一起去,这个逻辑处理应该怎么做?所以这个问题并不好做。
      在这里插入图片描述
  • 相关阅读:
    Java入门必备基础知识
    【OSS】服务端签名后直传实现阿里云存储上传文件
    微信qq拦截检测易语言代码
    DDD - 理论到落地从统一语言开始
    八股文之设计原则
    PS Raw中文增效工具Camera Raw 16
    Gateway服务网关
    数组some和every的区别
    Redis设计与实现(七)| 发布 & 订阅
    目前我国网络安全人才市场状况
  • 原文地址:https://blog.csdn.net/he_wen_jie/article/details/126264520