对于此题,可以利用「回溯」的思想求解:先尝试某一选择,若满足题目条件,则加到最终结果中;否则撤销该选择,重新进行下一次选择。

具体而言,利用「回溯」算法求解此题的步骤如图所示:
图片说明

import java.util.*;

public class Solution {

    ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();

    public ArrayList<ArrayList<Integer>> combinationSum2(int[] num, int target) {

        if (num == null || num.length == 0) {
            return result;
        }

        Arrays.sort(num);
        dfs(num, new ArrayList(), 0, target);
        return result;
    }

    public void dfs (int[] num, ArrayList<Integer> list, int index, int target) {

         if (target < 0) {
             return;
         }

        //我们这里做减法,当target为0 返回正确结果
        if (target == 0) {
            result.add(new ArrayList(list));
            return;
        }

        for (int i = index; i < num.length; i++) {

            //进行剪枝,当 num[i]>target的时候  肯定不能继续遍历
            if (target - num[i] < 0) {
                //因为已经排序过了 依次递增的 后面的肯定也就都不符合
                break;
            }

            //当有相等元素时候,跳过,避免重复
            if (i > index && num[i] == num[i-1]) {
                continue;
            }

            list.add(num[i]);

            //继续进行递归, 注意这里下标不是  index+1   而是  i+1,
            dfs(num, list, i+1, target - num[i]);

            //回溯  这里要remove掉 
            list.remove(list.size() - 1);
        }
    }
}