📅  最后修改于: 2023-12-03 15:41:58.152000             🧑  作者: Mango
递归是编程中一个非常重要的概念,也是面试中最常见的话题之一。递归练习问题套装4是通过不断地解决递归问题,来帮助程序员提高和巩固递归思想的练习。本题库共包含10道问题,每道题都有题目描述、输入样例、输出样例和解法分析。
给定一个二叉树,求它的最大深度。最大深度是从根节点到最远叶子节点的最长路径上的节点数。
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
给定一个不含重复元素的数组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
给定一个整数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
给定一个不含重复元素的数组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
有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)
给定一个由'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
给定一个正整数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
给定一个二叉树,判断它是否是二叉搜索树(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)
翻转一棵二叉树。交换每个节点的左右子树。
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
给定一个正整数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道难度不同、涵盖递归常见应用场景的题目,适合新手和有一定经验的程序员巩固和提高递归思想。递归虽然看起来简单,但是要想写出优美、高效的代码,需要不断的练习和实战,积累经验。