78. Subsets

 

 (面经 Find the number of subsets which the sum of min value in subset and max value in subset smaller or equal to the given target)

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        if(nums == null || nums.length == 0) return result;
        
        List<Integer> tmp = new ArrayList<>();
        dfs(nums, result, tmp, 0);
        return result; // if no return here, index would keep ++ int the follwing code, so must have a return 
    }
    private void dfs(int[] nums, List<List<Integer>> result, List<Integer> tmp, int index){
        if(index == nums.length){
            // so we need to new an object 
            result.add(new ArrayList(tmp)); // if result.add(tmp), the result would be [[][][][][][][][]]
            return;
        }
        
        // add current number
       
        tmp.add(nums[index]);
        dfs(nums, result, tmp, index + 1);
        // tmp.setLength(length); setLength is for string
        tmp.remove(tmp.size() - 1);
        
        // not add current number
        dfs(nums, result, tmp, index + 1);
    }
}

 

public List<String> allSubsets(char[] input){
  List<String> result = new ArrayList<>();
  if(input == null || input.length == 0){
    return result;
  }
  
  StringBuilder sb = new StringBuilder();
  dfs(result, sb, 0, input);
  return result;
}

private void dfs(List<String> result, StringBuilder sb, int index, char[] input){
  if(index == input.length){
    result.add(new sb.toString());// sb.toString() vs new String(sb);
    return;// important 
  }
  
  // add current char 
  dfs(result, sb.append(input.[index]), index + 1, input);
  // sb is changed, so backtrack
  // sb.remove(sb.length() - 1);
  // sb.deleteCharAt
  sb.deleteCharAt(sb.length() - 1);
  
  
  // not add current char 
  dfs(result, sb, index + 1, input);
}

  

char[] input = new char[]{a,b,c}

 

https://www.journaldev.com/3884/java-is-pass-by-value-and-not-pass-by-reference

First of all we should understand what is meant by pass by value or pass by reference.

  • Pass by Value: The method parameter values are copied to another variable and then the copied object is passed, that’s why it’s called pass by value.
  • Pass by Reference: An alias or reference to the actual parameter is passed to the method, that’s why it’s called pass by reference.

 


public static void swap(Object o1, Object o2){ //o1=50, o2=100 Object temp = o1; //temp=50, o1=50, o2=100 o1=o2; //temp=50, o1=100, o2=100 o2=temp; //temp=50, o1=100, o2=50 } //method terminated

Notice that we are changing values of o1 and o2 but they are copies of “red” and “blue” reference locations, so actually there is no change in the values of “red” and “blue” and hence the output.

 


private static void foo(Balloon balloon) { //baloon=100 balloon.setColor("Red"); //baloon=100 balloon = new Balloon("Green"); //baloon=200 balloon.setColor("Blue"); //baloon = 200 }

The first line is the important one, when we call a method the method is called on the Object at the reference location. At this point, balloon is pointing to 100 and hence it’s color is changed to Red.

In the next line, ballon reference is changed to 200 and any further methods executed are happening on the object at memory location 200 and not having any effect on the object at memory location 100. This explains the third line of our program output printing blue color=Red.

I hope above explanation clear all the doubts, just remember that variables are references or pointers and it’s copy is passed to the methods, so java is always pass by value

 

 

 

 

 

 

 

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

idea: three levels, every level: add current number, not add current number 

1 .        add 1,      not add 1 

2     add 2,      not add 2 

3     add 3      not add 3 

 

 

time complexity is O( 2 ^ N), N is the number of elements , space O(1)

 

                                O(not adding anthing)

        1       O

       /   \     / \

      2  O    2  O

     / \  /\   /\  /\

    3 O    3  O     3 O .  3 O

 

 

 

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]


A general approach to backtracking questions in Java (Subsets, Permutations, Combination Sum, Palindrome Partitioning

https://leetcode.com/problems/subsets/discuss/27281/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)




This structure might apply to many other backtracking questions, but here I am just going to demonstrate Subsets, Permutations, and Combination Sum.

Subsets : https://leetcode.com/problems/subsets/


Given a set of distinct integers, nums, return all possible subsets (the power set).


Note: The solution set must not contain duplicate subsets.


Example:


Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> list = new ArrayList<>(); Arrays.sort(nums); // no need to sort backtrack(list, new ArrayList<>(), nums, 0); return list; } private void backtrack(List<List<Integer>> list , List<Integer> tempList, int [] nums, int start){ list.add(new ArrayList<>(tempList)); for(int i = start; i < nums.length; i++){ tempList.add(nums[i]); backtrack(list, tempList, nums, i + 1); tempList.remove(tempList.size() - 1); } }



Subsets II (contains duplicates) : https:
//leetcode.com/problems/subsets-ii/

Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).


Note: The solution set must not contain duplicate subsets.


Example:


Input: [1,2,2]
Output:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]


public List<List<Integer>> subsetsWithDup(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, 0);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int start){
    list.add(new ArrayList<>(tempList));
    for(int i = start; i < nums.length; i++){
        if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates
        tempList.add(nums[i]);
        backtrack(list, tempList, nums, i + 1);
        tempList.remove(tempList.size() - 1);
    }
} 
Permutations : https://leetcode.com/problems/permutations/

Given a collection of distinct integers, return all possible permutations.


Example:


Input: [1,2,3]
Output:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

public List<List<Integer>> permute(int[] nums) {
   List<List<Integer>> list = new ArrayList<>();
   // Arrays.sort(nums); // no need to sort
   backtrack(list, new ArrayList<>(), nums);
   return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
   if(tempList.size() == nums.length){
      list.add(new ArrayList<>(tempList));
   } else{
      for(int i = 0; i < nums.length; i++){ 
         if(tempList.contains(nums[i])) continue; // element already exists, skip
         tempList.add(nums[i]);
         backtrack(list, tempList, nums);
         tempList.remove(tempList.size() - 1);
      }
   }
} 


class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        
        dfs(res, new ArrayList<>(), nums, new boolean[nums.length]);
        return res;
    }
    private void dfs(List<List<Integer>> res, List<Integer> tmp, int[] nums, boolean[] used){
        if(tmp.size() == nums.length){
            res.add(new ArrayList<>(tmp));
            return;
        }
        
        for(int i = 0; i < nums.length; i++){
            if(used[i]) continue;
            used[i] = true;
            tmp.add(nums[i]);
            dfs(res, tmp, nums, used);
            used[i] = false;
            tmp.remove(tmp.size() - 1);
        }
        
    }
}

 



Permutations II (contains duplicates) : https:
//leetcode.com/problems/permutations-ii/

Given a collection of numbers that might contain duplicates, return all possible unique permutations.


Example:


Input: [1,1,2]
Output:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]
public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, boolean [] used){
    if(tempList.size() == nums.length){
        list.add(new ArrayList<>(tempList));
    } else{
        for(int i = 0; i < nums.length; i++){
            if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue; // like in this example, the second 1 's permute is ignored
            used[i] = true; 
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, used);
            used[i] = false; 
            tempList.remove(tempList.size() - 1);
        }
    }
}
Combination Sum : https://leetcode.com/problems/combination-sum/

Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.


The same repeated number may be chosen from candidates unlimited number of times.


Note:


  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:


Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
  [7],
  [2,2,3]
]

Example 2:


Input: candidates = [2,3,5], target = 8,
A solution set is:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]


public List<List<Integer>> combinationSum(int[] nums, int target) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums); // no need to sort
    backtrack(list, new ArrayList<>(), nums, target, 0);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int remain, int start){
    if(remain < 0) return;
    else if(remain == 0) list.add(new ArrayList<>(tempList));
    else{ 
        for(int i = start; i < nums.length; i++){
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, remain - nums[i], i); // not i + 1 because we can reuse same elements
            tempList.remove(tempList.size() - 1);
        }
    }
}



Combination Sum II (can
't reuse same element) : https://leetcode.com/problems/combination-sum-ii/

Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
  [1,2,2],
  [5]
]


public List<List<Integer>> combinationSum2(int[] nums, int target) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, target, 0);
    return list;
    
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int remain, int start){
    if(remain < 0) return;
    else if(remain == 0) list.add(new ArrayList<>(tempList));
    else{
        for(int i = start; i < nums.length; i++){
            if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, remain - nums[i], i + 1);
            tempList.remove(tempList.size() - 1); 
        }
    }
} 


Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

Example:

Input: "aab"
Output:
[
  ["aa","b"],
  ["a","a","b"]
]


Palindrome Partitioning : https://leetcode.com/problems/palindrome-partitioning/

 

public List<List<String>> partition(String s) {
   List<List<String>> list = new ArrayList<>();
   backtrack(list, new ArrayList<>(), s, 0);
   return list;
}

public void backtrack(List<List<String>> list, List<String> tempList, String s, int start){
   if(start == s.length())
      list.add(new ArrayList<>(tempList));
   else{
      for(int i = start; i < s.length(); i++){
         if(isPalindrome(s, start, i)){
            tempList.add(s.substring(start, i + 1));
            backtrack(list, tempList, s, i + 1);
            tempList.remove(tempList.size() - 1);
         }
      }
   }
}

public boolean isPalindrome(String s, int low, int high){
   while(low < high)
      if(s.charAt(low++) != s.charAt(high--)) return false;
   return true;
} 
 

posted on 2018-07-18 07:34  猪猪&#128055;  阅读(118)  评论(0)    收藏  举报

导航