40. 组合总和 II
**给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用 一次 **
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出: [ [1,1,6], [1,2,5], [1,7], [2,6] ]
输入: candidates = [2,5,2,1,2], target = 5,
输出: [ [1,2,2], [5] ]
注意🐋:
- 解集不能包含重复的组合
- 排序
class Solution {
private void operate(List<Integer> nowSta,int target, int tot, int begin, int[] candidates){
//1.递归终止条件
if(tot == target){
res.add(new ArrayList<>(nowSta));
return ;
}
for(int i = begin;i < candidates.length;i++){
//2.如果当前的数值大于目标值,就不用再往下搜索了
if(tot + candidates[i] > target) {
continue;
}
//3.如果这个当前的数值和上一个数值相同,也就不用再往下搜索了
if(i != begin && candidates[i] == candidates[i - 1]) {
continue;
}
//4.将当前的数值加入到候选集中
nowSta.add(candidates[i]);
//5.递归-继续搜索
DFS(nowSta,target,tot + candidates[i],i + 1,candidates);
//6.将当前的数值从候选集中移除
nowSta.remove(nowSta.size() - 1);
}
}
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
//排序
Arrays.sort(candidates);
List<Integer> sta = new ArrayList<>();
operate(sta,target,0,0,candidates);
return res;
}
}
66. 加一
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321。
输入:digits = [0]
输出:[1]
注意🐋:
- 注意进位
class Solution {
public int[] plusOne(int[] digits) {
for(int i = digits.length - 1;i >= 0;i--){
digits[i] ++;
digits[i] %= 10;
//1.如果不是9,就不用进位了
if(digits[i] != 0)
{
return digits;
}
}
//2.如果是9,进位
digits = new int[digits.length + 1];
//3.第一位为1
digits[0] = 1;
//4.返回
return digits;
}
}
47. 全排列 II
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
输入:nums = [1,1,2]
输出: [[1,1,2], [1,2,1], [2,1,1]]
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
注意🐋:
- 注意判重
- 注意顺序
class Solution {
List<List<Integer>> res = new ArrayList<>();
//1.定义一个 boolean 数组,用来标记当前的数值是否被使用过
boolean[] vis;
//2.定义一个数组,用来存储当前的排列
int[] numsIn;
private void operation(List<Integer> nowSta){
if(nowSta.size() == numsIn.length){
// 将当前的排列加入到结果集中。
// 注意:这里要 new 一个新的对象,否则会出现问题,因为 nowSta 是一个引用类型,如果不 new 一个新的对象,
// 那么后面的操作会影响到 nowSta,从而影响到 res,
// 从而影响到最终的结果。
res.add(new ArrayList<>(nowSta));
return ;
}
for(int i = 0;i < numsIn.length;i++){
//1.如果当前的数值已经被使用过了,或者当前的数值和上一个数值相同,且上一个数值没有被使用过,则不再往下搜索了
// 例如:[1,1,2],第一次搜索到 1,第二次搜索到 1,此时第二个 1 没有被使用过,所以可以继续搜索
if(vis[i] || (i > 0 && numsIn[i] == numsIn[i - 1] && !vis[i - 1])) {
continue;
}
//2.将当前的数值加入到候选集中
nowSta.add(numsIn[i]);
//3.将当前的数值标记为已使用
vis[i] = true;
//4.递归-继续搜索
operation(nowSta);
//5.将当前的数值从候选集中移除
nowSta.remove(nowSta.size() - 1);
//6.将当前的数值标记为未使用
vis[i] = false;
}
}
public List<List<Integer>> permuteUnique(int[] nums) {
numsIn = nums;
List<Integer> ans = new ArrayList<>();
//1.对数组进行排序
Arrays.sort(numsIn);
//2.初始化 boolean 数组
vis = new boolean[nums.length];
//3.开始搜索
operation(ans);
//4.返回结果
return res;
}
}