1. 回溯算法核心思想与实战应用
回溯算法是解决组合、排列、子集等问题的利器。作为一名算法工程师,我发现在实际面试和工程应用中,能否熟练运用回溯算法往往能直接体现一个开发者的基本功。回溯的本质就是暴力穷举,但通过合理的剪枝和优化,可以大幅提升效率。
回溯算法最迷人的地方在于它把复杂问题转化为树形结构的遍历过程。就像搭积木一样,我们一步步构建可能的解,遇到不符合条件的就回退,直到找到所有可行解。这种"试错+回退"的机制,让许多看似复杂的问题变得清晰可控。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 递增子序列问题深度解析
2.1 问题定义与树形结构拆解
递增子序列问题要求找出数组中所有长度至少为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]等。
关键点:子序列不要求连续,但必须保持原数组中的相对顺序且非严格递增
将这个问题转化为树形结构时,每个节点代表一个决策点:是否选择当前数字加入序列。树的每一层对应数组中的一个元素,分支代表选择或不选择该元素。
2.2 核心代码实现与剪枝策略
java复制public static List<List<Integer>> findSubsequences(int[] nums) {
ArrayList<List<Integer>> res = new ArrayList<>();
findArr(nums, 0, new ArrayList<>(), res);
return res;
}
public static void findArr(int[] nums, int index, List<Integer> arr, List<List<Integer>> res) {
if (arr.size() > 1) {
res.add(new ArrayList<>(arr));
}
HashSet<Integer> set = new HashSet<>();
for (int i = index; i < nums.length; i++) {
if (set.contains(nums[i]) || (!arr.isEmpty() && nums[i] < arr.getLast())) {
continue;
}
arr.add(nums[i]);
set.add(nums[i]);
findArr(nums, i + 1, arr, res);
arr.removeLast();
}
}
这段代码有几个关键设计点:
- 使用HashSet进行同层去重,避免选择相同元素产生重复子序列
- 检查当前数字是否大于等于序列最后一个元素,保证递增性
- 通过ind
