1. 算法训练营第25天任务解析
今天的三道题目都属于回溯算法的经典应用场景,但各自考察的重点有所不同。491题关注如何在无序数组中寻找特定条件的子序列,46题是回溯的入门级全排列问题,47题则在此基础上增加了去重逻辑。这三道题组合在一起,恰好构成了回溯算法从基础到进阶的完整学习路径。
1.1 递增子序列问题(491题)
给定一个整型数组,找出所有不同的递增子序列,要求子序列长度至少为2。这里的"递增"定义为序列中任意两个相邻元素,前一个不大于后一个。例如输入[4,6,7,7],输出应包含[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]等。
这个问题的难点在于:
- 原数组可能包含重复元素
- 需要保证结果中的子序列不重复
- 子序列要求保持原数组中的相对顺序
1.2 全排列问题(46题)
给定一个不含重复数字的数组,返回所有可能的全排列。这是回溯算法最经典的入门问题,例如输入[1,2,3],输出应包含[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]六种排列。
这个问题帮助我们理解:
- 如何通过交换元素实现排列
- 回溯过程中状态的回退机制
- 递归终止条件的判断
1.3 含重复元素的全排列(47题)
在46题基础上增加了难度:数组可能包含重复数字,要求返回不重复的全排列。例如输入[1,1,2],输出应为[1,1,2],[1,2,1],[2,1,1]。
这个变种问题的核心在于:
- 如何避免生成重复的排列
- 剪枝条件的合理设置
- 排序预处理的重要性
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 递增子序列的解法与优化
2.1 基础回溯解法
最直观的思路是使用回溯算法枚举所有可能的子序列,然后筛选出符合条件的。伪代码如下:
python复制def findSubsequences(nums):
result = []
path = []
def backtrack(start):
if len(path) >= 2:
result.append(path[:])
used = set() # 用于本层去重
