🔥 个人主页: 黑洞晓威
😀你不必等到非常厉害,才敢开始,你需要开始,才会变的非常厉害。
40.组合总和II
给定一个候选人编号的集合 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用 一次 。
**注意:**解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
问题分析
首先,我们需要明确题目中的要求和限制条件:
- 给定一个正整数数组
candidates
和一个目标数target
。 - 数组中的每个数字在每个组合中只能使用一次。
- 解集不能包含重复的组合。
我们需要找出所有满足条件的组合,将它们以列表形式返回。
解题思路
-
排序数组:为了方便后续的剪枝操作和去重操作,我们首先对数组进行排序。
-
回溯搜索:使用回溯算法进行搜索,定义一个回溯函数
backtrack
,参数包括当前的目标数target
、搜索起始位置start
、当前组合路径path
和结果列表result
。 -
搜索过程
:在回溯函数中,我们逐个遍历数组中的数字,并进行如下操作:
- 如果当前目标数为0,说明找到了一组满足条件的组合,将其加入结果列表中。
- 如果当前目标数小于0,说明当前组合不合法,直接返回。
- 对于每个数字,如果它和前一个数字相同且在同一层级上,则跳过,避免重复组合。
- 否则,将当前数字加入组合路径,递归搜索下一层可能的组合,更新目标数和搜索起始位置,然后回溯移除最后一个数字,继续搜索下一个数字。
-
返回结果:最终返回结果列表中的所有组合。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class CombinationSumII {public static List<List<Integer>> combinationSum2(int[] candidates, int target) {List<List<Integer>> result = new ArrayList<>();Arrays.sort(candidates); // 对候选数组排序,方便剪枝和去重backtrack(candidates, target, 0, new ArrayList<>(), result);return result;}private static void backtrack(int[] candidates, int target, int start, List<Integer> path, List<List<Integer>> result) {if (target == 0) {// 找到一组组合,加入结果列表中result.add(new ArrayList<>(path));return;}if (target < 0) {// 当前组合不合法,直接返回return;}for (int i = start; i < candidates.length; i++) {// 避免重复组合,跳过相同的数字if (i > start && candidates[i] == candidates[i - 1]) {continue;}path.add(candidates[i]); // 将当前候选数加入组合路径// 递归搜索下一层可能的组合,起始位置为 i+1,因为每个数字只能使用一次backtrack(candidates, target - candidates[i], i + 1, path, result);path.remove(path.size() - 1); // 回溯,移除最后一个候选数}}public static void main(String[] args) {int[] candidates1 = {10, 1, 2, 7, 6, 1, 5};int target1 = 8;List<List<Integer>> result1 = combinationSum2(candidates1, target1);System.out.println(result1); // 输出 [[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]int[] candidates2 = {2, 5, 2, 1, 2};int target2 = 5;List<List<Integer>> result2 = combinationSum2(candidates2, target2);System.out.println(result2); // 输出 [[1, 2, 2], [5]]}
}
701. 二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点 root
和要插入树中的值 value
,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
示例 1:
输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:
示例 2:
输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]
示例 3:
输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]
问题分析
插入操作需要考虑二叉搜索树的特性,即左子树的值小于根节点的值,右子树的值大于根节点的值。因此,在插入节点时,我们需要找到合适的位置插入,并保持树的二叉搜索树性质。
解题思路
我们可以通过递归或迭代的方式来实现插入操作。具体步骤如下:
- 如果根节点为空,则直接将新节点作为根节点返回。
- 如果要插入的值小于根节点的值,则递归插入到左子树中。
- 如果要插入的值大于根节点的值,则递归插入到右子树中。
- 最后返回根节点。
class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }
}public class InsertIntoBST {public TreeNode insertIntoBST(TreeNode root, int val) {if (root == null) {return new TreeNode(val);}if (val < root.val) {root.left = insertIntoBST(root.left, val);} else if (val > root.val) {root.right = insertIntoBST(root.right, val);}return root;}public static void main(String[] args) {// 示例用例TreeNode root = new TreeNode(4);root.left = new TreeNode(2);root.right = new TreeNode(7);root.left.left = new TreeNode(1);root.left.right = new TreeNode(3);int val = 5;InsertIntoBST solution = new InsertIntoBST();TreeNode result = solution.insertIntoBST(root, val);// 输出结果System.out.println(result);}
}