93.复原IP地址

class Solution {
    List<String> result = new ArrayList<>();
    public List<String> restoreIpAddresses(String s) {
        if(s.length() > 12) return result;
        f(s,0,0);
        return result;
    }
    void f(String s,int startIndex,int pointNum){
        if(pointNum == 3){
            if(isValid(s,startIndex,s.length() - 1)){
                result.add(s);
            }
            return;
        }
        for (int i = startIndex; i < s.length(); i++) {
        if(isValid(s, startIndex, i)){
            s = s.substring(0,i + 1) + "." + s.substring(i + 1);
            pointNum++;
            f(s,i + 2,pointNum);
            pointNum--;
            s = s.substring(0,i+1) + s.substring(i+2);//回溯去掉逗号
        }else{
            break;
        }
        }
 
     
    }
    boolean isValid(String s,int startIndex,int end){
          if (startIndex > end) {
            return false;
        }
        if(s.charAt(startIndex) == '0' && startIndex != end){
            return false;
        }
        int num = 0;
        for(int i = startIndex;i <= end;i++){
             if (s.charAt(i) > '9' || s.charAt(i) < '0') { // 遇到⾮数字字符不合法
                return false;
            }
            num = num*10 + (s.charAt(i) - '0');
            if(num > 255){
                return false;
            }
        }
        return true;
    }
78.子集


class Solution {
     List<List<Integer>> list = new ArrayList<>();
     LinkedList<Integer> res = new LinkedList<>();
    public List<List<Integer>> subsets(int[] nums) {
       f(nums,0);
       return list;
    }
    void f(int[] nums,int start){
        list.add(new ArrayList(res));
        //递归终止条件:剩余集合为空的时候,就是叶子节点。
        if(start == nums.length){
            return;
        }
        for(int i = start;i < nums.length;i++){
            res.add(nums[i]);
            f(nums,i+1);
            res.removeLast();
        }
    }
}
90.子集II


class Solution {
    List<List<Integer>> list = new ArrayList<>();
    LinkedList<Integer> res = new LinkedList<>();
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        f(nums,0);
        return list;
    }
    void f(int[] nums,int start){
       list.add(new ArrayList(res));
        if(start == nums.length){
            return;
        }
        for(int i = start;i < nums.length;i++){
            if(i > start && nums[i] == nums[i-1]) continue;
            res.add(nums[i]);
            f(nums,i+1);
            res.removeLast();
        }
    }
}
 使用used数组
class Solution {
   List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
   LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
   boolean[] used;
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        if (nums.length == 0){
            result.add(path);
            return result;
        }
        Arrays.sort(nums);
        used = new boolean[nums.length];
        subsetsWithDupHelper(nums, 0);
        return result;
    }
    
    private void subsetsWithDupHelper(int[] nums, int startIndex){
        result.add(new ArrayList<>(path));
        if (startIndex >= nums.length){
            return;
        }
        for (int i = startIndex; i < nums.length; i++){
            if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]){
                continue;
            }
            path.add(nums[i]);
            used[i] = true;
            subsetsWithDupHelper(nums, i + 1);
            path.removeLast();
            used[i] = false;
        }
    }
}                










