LeetCode 热题100 -40、66、47

107 阅读2分钟

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;
    }
}