📜  递归练习问题套装4(1)

📅  最后修改于: 2023-12-03 15:41:58.152000             🧑  作者: Mango

递归练习问题套装4

简介

递归是编程中一个非常重要的概念,也是面试中最常见的话题之一。递归练习问题套装4是通过不断地解决递归问题,来帮助程序员提高和巩固递归思想的练习。本题库共包含10道问题,每道题都有题目描述、输入样例、输出样例和解法分析。

问题列表
1. 二叉树的最大深度

题目描述

给定一个二叉树,求它的最大深度。最大深度是从根节点到最远叶子节点的最长路径上的节点数。

输入样例

    3
   / \
  9  20
    /  \
   15   7

输出样例

3

解法分析

该问题可使用递归解决。二叉树的最大深度等于左右子树的最大深度加1的最大值。递归过程中需要考虑空节点的情况。

代码片段:

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        else:
            left_height = self.maxDepth(root.left)
            right_height = self.maxDepth(root.right)
            return max(left_height, right_height) + 1
2. 找出所有子集

题目描述

给定一个不含重复元素的数组nums,求它的所有子集。

输入样例

nums = [1,2,3]

输出样例

[[],[1],[1,2],[1,2,3],[1,3],[2],[2,3],[3]]

解法分析

该问题可使用递归解决。子集可以由前一个子集再加上一个元素得到。递归过程中需要考虑空数组的情况。

代码片段:

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        def dfs(start, path):
            res.append(path)
            for i in range(start, n):
                dfs(i+1, path+[nums[i]])
            
        n = len(nums)
        res = []
        dfs(0, [])
        return res
3. 括号生成

题目描述

给定一个整数n,生成所有由n对括号组成的合法括号序列。

输入样例

n = 3

输出样例

["((()))","(()())","(())()","()(())","()()()"]

解法分析

该问题可使用递归解决。假设当前已经匹配了left个左括号和right个右括号,下一步可以加上左括号或者右括号。递归过程中需要考虑剩余左括号个数不能大于右括号个数的情况。

代码片段:

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        def dfs(left, right, path):
            if left == 0 and right == 0:
                res.append(path)
                return
            if left > right:
                return
            if left > 0:
                dfs(left-1, right, path+'(')
            if right > 0:
                dfs(left, right-1, path+')')
                
        res = []
        dfs(n, n, '')
        return res
4. 全排列

题目描述

给定一个不含重复元素的数组nums,求它的所有排列。

输入样例

nums = [1,2,3]

输出样例

[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

解法分析

该问题可使用递归解决。假设当前已经确定了前i个数的排列,下一步可以把第i+1个数和前面的数交换一下,使得前i+1个数的排列是正确的。递归过程中需要考虑重复的情况。

代码片段:

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def dfs(start):
            if start == n:
                res.append(nums[:])
            for i in range(start, n):
                nums[start], nums[i] = nums[i], nums[start]
                dfs(start+1)
                nums[start], nums[i] = nums[i], nums[start]
            
        n = len(nums)
        res = []
        dfs(0)
        return res
5. 爬楼梯

题目描述

有n级楼梯,每次可以爬1级或2级,问有多少种不同的方法可以爬到楼顶。

输入样例

n = 3

输出样例

3

解法分析

该问题可使用递归解决。假设f(n)表示爬到n级楼梯的方法数,那么f(n) = f(n-1) + f(n-2)。递归过程中需要考虑n为1或2的情况。

代码片段:

class Solution:
    def climbStairs(self, n: int) -> int:
        if n == 1:
            return 1
        if n == 2:
            return 2
        return self.climbStairs(n-1) + self.climbStairs(n-2)
6. 岛屿数量

题目描述

给定一个由'1'(陆地)和'0'(水)组成的二维网格,求岛屿的数量。岛屿被水包围,由水平方向或垂直方向上相邻的陆地连接而成。假设所有边界都是水。

输入样例

grid = [
  ['1','1','0','0','0'],
  ['1','1','0','0','0'],
  ['0','0','1','0','0'],
  ['0','0','0','1','1']
]

输出样例

3

解法分析

该问题可使用递归解决。遍历整个网格,遇到陆地就使用dfs把相邻的陆地都标记为已访问。计数器加一即可。

代码片段:

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        def dfs(i, j):
            if i < 0 or i >= m or j < 0 or j >= n or grid[i][j] == '0':
                return
            grid[i][j] = '0'
            dfs(i-1, j)
            dfs(i+1, j)
            dfs(i, j-1)
            dfs(i, j+1)
        
        if not grid:
            return 0
        m, n = len(grid), len(grid[0])
        count = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    dfs(i, j)
                    count += 1
        return count
7. 整数拆分

题目描述

给定一个正整数n,将它分解成至少两个正整数的和,求这些正整数的最大乘积。

输入样例

n = 10

输出样例

36

解法分析

该问题可使用递归解决。假设f(n)表示把n分解成至少两个正整数的和,这些正整数的最大乘积。则f(n) = max{i*(n-i), i*f(n-i)},其中i是最后一个加入的数。递归过程中需要考虑n为1或2的情况。

代码片段:

class Solution:
    def integerBreak(self, n: int) -> int:
        if n == 1:
            return 1
        if n == 2:
            return 1
        res = 0
        for i in range(1, n):
            res = max(res, i*(n-i), i*self.integerBreak(n-i))
        return res
8. 验证二叉搜索树

题目描述

给定一个二叉树,判断它是否是二叉搜索树(BST)。BST的左子树中所有节点的值都小于根节点的值,BST的右子树中所有节点的值都大于根节点的值,并且左右子树也都是BST。

输入样例

    2
   / \
  1   3

输出样例

True

解法分析

该问题可使用递归解决。一个二叉树是BST,等价于它满足中序遍历是一个递增的序列。递归过程中需要记录上一个遍历到的节点,以方便比较大小。

代码片段:

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        def dfs(node):
            nonlocal prev
            if not node:
                return True
            if not dfs(node.left):
                return False
            if node.val <= prev:
                return False
            prev = node.val
            return dfs(node.right)
        
        prev = float('-inf')
        return dfs(root)
9. 翻转二叉树

题目描述

翻转一棵二叉树。交换每个节点的左右子树。

输入样例

    4
   / \
  2   7
 / \ / \
1  3 6  9

输出样例

    4
   / \
  7   2
 / \ / \
9  6 3  1

解法分析

该问题可使用递归解决。递归地交换左右子树即可。

代码片段:

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
        left = root.left
        right = root.right
        root.left = self.invertTree(right)
        root.right = self.invertTree(left)
        return root
10. 完全平方数

题目描述

给定一个正整数n,判断它是否由完全平方数相加得到。可以使用的完全平方数是包括1的。

输入样例

n = 13

输出样例

False

解法分析

该问题可使用递归解决。假设f(n)表示把n分解成完全平方数相加得到的最少数量,那么f(n) = min(f(n-i) + 1),其中i是最后一个加入的完全平方数。递归过程中需要记录已经访问过的状态,避免重复计算。

代码片段:

class Solution:
    def numSquares(self, n: int) -> int:
        def dfs(n):
            if n == 0:
                return 0
            if n in memo:
                return memo[n]
            res = float('inf')
            for i in range(1, int(n**0.5) + 1):
                res = min(res, dfs(n-i*i) + 1)
            memo[n] = res
            return res
        
        memo = {}
        return dfs(n)
总结

递归练习问题套装4包含了10道难度不同、涵盖递归常见应用场景的题目,适合新手和有一定经验的程序员巩固和提高递归思想。递归虽然看起来简单,但是要想写出优美、高效的代码,需要不断的练习和实战,积累经验。