递归:解题思路

Posted 我家大宝最可爱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归:解题思路相关的知识,希望对你有一定的参考价值。

  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. 合并两个有序链表
    原问题是合并两个链表,当我们提取出最小值的时候,子问题就可以变成合并缩小规模后的两条链表,例如合并两个链表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. 反转链表
    原问题是反转[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
        

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

  1. 两个数组的交集
    这个问题并不能使用递归解决,但是因为很像递归,我单独分析一下。假如我们子问题已经求出解了,现在的问题是如何把元素1和子问题的解[2,4] 合并到一起去,这个逻辑处理应该怎么做?所以这个问题并不好做。

以上是关于递归:解题思路的主要内容,如果未能解决你的问题,请参考以下文章

7-17 汉诺塔的非递归实现(25 分)(有待改进)

递归3之汉诺塔的实现

汉诺塔问题java实现

递归解决汉诺塔问题

C语言详解:函数递归专题

华为OD机试真题Java实现子序列长度真题+解题思路+代码(2022&2023)