W
e
l
c
o
m
e
: )

40.组合总和Ⅱ

40.组合总和Ⅱ

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。

  • 跟上一题组合总和一样的解法
  • 这次规定只能使用一次数字,那么我们可以添加一个判定的数组
  • 数组的大小和candidates大小一致,判定数组的每一位对应candidates的每一位,在使用到这个数字的时候,在判定数组的相应位置写上1,代表我使用了这个数,在搜索完毕的时候归0,表示归还.
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<>();
        for (int i = 0; i < candidates.length; i++){
            List<Integer> temp = new ArrayList<>();
            // 判定用数字
            int[] pos = new int[candidates.length];
            temp.add(candidates[i]);
            // 使用时写上1
            pos[i] = 1;
            searchCandidatesToSum2(result,temp,candidates[i],pos,candidates,target);
            temp.remove((Integer) candidates[i]);
            // 搜索结束归0
            // 下面的函数内部逻辑 同理
            pos[i] = 0;
        }

        return result;
    }

    private void searchCandidatesToSum2(List<List<Integer>> result, List<Integer> temp, int tempSum, int[] pos, int[] candidates, int target) {
        // 与之前的文章一样的逻辑
        // 在此不多赘述
        if( tempSum > target ){
            return;
        }
        if( tempSum == target ){
            if( findResult(result,temp) ){
                temp.sort(Comparator.naturalOrder());
                result.add(new ArrayList<>(temp));
            }
            return;
        }
        for (int i = 0; i < candidates.length; i++) {
            if( pos[i] != 1 ){
                temp.add(candidates[i]);
                pos[i] = 1;
                searchCandidatesToSum2(result,temp,tempSum+candidates[i],pos,candidates,target);
                pos[i] = 0;
                temp.remove((Integer)candidates[i]);
            }
        }
    }
    // 复制了之前的代码
    // 函数重用 XD
    private boolean findResult(List<List<Integer>> result, List<Integer> temp) {
        for (List<Integer> item :
                result) {
            /**
             * 当集合大小相同时进行比对
             */
            if( item.size() == temp.size() ){
                List<Integer> newItem = new ArrayList<>(item);
                for (Integer i : temp) {
                    /**
                     * 当newItem中存在temp的第i个目标时
                     * 从newItem中删去当前目标相同的数字
                     */
                    if(newItem.contains(i)){
                        newItem.remove(i);
                    }
                }
                /**
                 * 若newItem的大小为0时
                 * 说明newItem与temp的内容完全相同
                 * 则返回false
                 */
                if( newItem.size() == 0 ){
                    return false;
                }
            }
        }
        return true;
    }
}
posted @ 2019-09-28 09:40  未来科技C级员工  阅读(112)  评论(0编辑  收藏  举报