Permutations: http://www.lintcode.com/en/problem/permutations/#
- or use used[i] to record used elements, instead to list.contains(..)
- O(n!)
public ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> nums) {
ArrayList<ArrayList<Integer>> rst = new ArrayList<>();
if (nums == null || nums.size() == 0) {
return rst;
}
ArrayList<Integer> list = new ArrayList<>();
helper(list, rst, nums);
return rst;
}
private void helper(ArrayList<Integer> list,
ArrayList<ArrayList<Integer>> rst, ArrayList<Integer> nums) {
if (list.size() == nums.size()) {
rst.add(new ArrayList<>(list));
}
for (int i = 0; i < nums.size(); i++) {
if (list.contains(nums.get(i))) {
continue;
}
list.add(nums.get(i));
helper(list, rst, nums);
list.remove(list.size() - 1);
}
}
public ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> nums) {
// write your code here
ArrayList<ArrayList<Integer>> rst = new ArrayList<ArrayList<Integer>>();
if(nums == null || nums.size() == 0) return rst;
boolean[] used = new boolean[nums.size()];
dfs(rst, new ArrayList<Integer>(), nums, used);
return rst;
}
private void dfs(ArrayList<ArrayList<Integer>> rst, List<Integer> list,
ArrayList<Integer> nums, boolean[] used){
if(list.size() == nums.size()){
rst.add(new ArrayList<Integer>(list));
return;
}
for(int i = 0; i < nums.size(); i++){
if(used[i]) continue;
list.add(nums.get(i));
used[i] = true;
dfs(rst, list, nums, used);
used[i] = false;
list.remove(list.size() - 1);
}
}
Permutations ii: http://www.lintcode.com/en/problem/permutations-ii/
- visited[] to record the element visited. <=> list.contains(..)
- continue 的两种情况:
- 正在访问的 visited[i] == 1
- 正在访问的 和 之前访问过的 值相同
public ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
// write your code here
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
if (nums == null || nums.size() == 0) {
return result;
}
Collections.sort(nums);
List<Integer> list = new ArrayList<>();
int[] visited = new int[nums.size()];
helper(result, list, nums, visited);
return result;
}
private void helper(ArrayList<ArrayList<Integer>> result,
List<Integer> list, ArrayList<Integer> nums,
int[] visited) {
if (list.size() == nums.size()) {
result.add(new ArrayList<Integer>(list));
return;
}
for (int i = 0; i < nums.size(); i++) {
// 既要保证 1.跳过重复元素 2.跳过已存在元素
//因为是前一个元素 所以 0表示访问完成 而非 未访问
if (visited[i] == 1 ||
(i != 0 && nums.get(i).equals(nums.get(i - 1))
&& visited[i - 1] == 0)){
continue;
}
visited[i] = 1;
list.add(nums.get(i));
helper(result, list, nums, visited);
list.remove(list.size() - 1);
visited[i] = 0;
}
}
public ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums){
ArrayList<ArrayList<Integer>> rst = new ArrayList<ArrayList<Integer>>();
if(nums == null || nums.size() == 0) return rst;
boolean[] used = new boolean[nums.size()];
Collections.sort(nums);
dfs(rst, new ArrayList<Integer>(), nums, used);
return rst;
}
private void dfs(ArrayList<ArrayList<Integer>> rst, List<Integer> list,
ArrayList<Integer> nums, boolean[] used){
if(list.size() == nums.size()){
rst.add(new ArrayList<Integer>(list));
return;
}
for(int i = 0; i < nums.size(); i++){
if(used[i]) continue;
list.add(nums.get(i));
used[i] = true;
dfs(rst, list, nums, used);
used[i] = false;
list.remove(list.size() - 1);
while(i + 1 < nums.size() && nums.get(i + 1) == nums.get(i)){
i ++;
}
}
}
Combinations: http://www.lintcode.com/en/problem/combinations/
- prev 记录上一个位置. 因为non duplicate, so
dfs(... i + 1)
- 不回头地向前 用prev 记录位置
- O(k * C(k, n))
public List<List<Integer>> combine(int n, int k) {
// write your code here
List<List<Integer>> rst = new ArrayList<>();
if (n == 0) return rst;
List<Integer> list = new ArrayList<>();
dfs(rst, list, n, k, 1);
return rst;
}
private void dfs(List<List<Integer>> rst, List<Integer> list, int n, int k, int prev) {
if (list.size() == k) {
rst.add(new ArrayList<>(list));
return;
}
for (int i = prev; i <= n; i++) {
list.add(i);
dfs(rst, list, n, k, i + 1);
list.remove(list.size() - 1);
}
}
Subsets: http://www.lintcode.com/en/problem/subsets/
- no need for return, since it will automatically end;
- use
prev
to record position. non duplicate, sodfs(... i + 1)
- notice: i + 1, not
pos + 1 - O(n*2^n)
public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
ArrayList<ArrayList<Integer>> rst = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
if (nums == null || nums.length == 0) {
// 注意 input 为 [] 时,output 为 [[]]
rst.add(list);
return rst;
}
Arrays.sort(nums);
dfs(nums, rst, list, 0);
return rst;
}
private void dfs(int[] nums, ArrayList<ArrayList<Integer>> rst,
ArrayList<Integer> list, int prev) {
rst.add(new ArrayList<>(list));
for (int i = prev; i < nums.length; i++) {
list.add(nums[i]);
dfs(nums, rst, list, i + 1);
list.remove(list.size() - 1);
}
}
Subsets ii - with dup: https://leetcode.com/problems/subsets-ii/#/description
- to get the next no-dup element:
while(i + 1 < nums.length && nums[i] == nums[i + 1]) i++;
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> rst = new ArrayList<>();
Arrays.sort(nums);
dfs(rst, new ArrayList<>(), nums, 0);
return rst;
}
private void dfs(List<List<Integer>> rst, List<Integer> list, int[] nums, int start){
rst.add(new ArrayList<Integer>(list));
for(int i = start; i < nums.length; i++){
list.add(nums[i]);
dfs(rst, list, nums, i + 1);
list.remove(list.size() - 1);
while(i + 1 < nums.length && nums[i] == nums[i + 1]) i++;
}
}
Combination Sum: http://www.lintcode.com/en/problem/combination-sum/#
- can use same elements. input may have dup.
- prev 记录前一个位置. 因为可以 duplicate so
i = prev
cf. Combinations - 注意 input 自带duplicate 的 case e.g. [2, 2, 3], 在 for loop 中 filter 即可
- Be aware:
if (i != 0 && candidates[i] == candidates[i - 1]) { continue; }
- not only skip dup in same level
- but also skip dup in sub tree (which cause error in combination sum ii)
- O(k * 2^n)
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// write your code here
List<List<Integer>> rst = new ArrayList<>();
if (candidates == null || candidates.length == 0) return rst;
List<Integer> list = new ArrayList<>();
Arrays.sort(candidates);
dfs(rst, list, candidates, target, 0);
return rst;
}
private void dfs(List<List<Integer>> rst, List<Integer> list, int[] candidates, int target, int prev) {
if (target < 0) return;
if (target == 0) {
rst.add(new ArrayList<>(list));
return;
}
for (int i = prev; i < candidates.length; i++) {
// e.g. [2, 2, 3], need to skip the second 2
//if (i != 0 && candidates[i] == candidates[i - 1]) {
// continue;
//}
list.add(candidates[i]);
dfs(rst, list, candidates, target - candidates[i], i);
list.remove(list.size() - 1);
while (i+1 < candidates.length && candidates[i] == candidates[i+1]) i++;
}
}
Combination Sum ii:
- can not use same element, while input has dup
- use
while ( i + 1 < candidates.length && candidates[i + 1] == candidates[i]) i++;
to skip dup in raw input if (i != 0 && candidates[i] == candidates[i - 1]) { continue; }
will skip both dup in input array and sub tree.- use
dfs(... i + 1)
cfdfs(...i)
in Combination Sum i
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> rst = new ArrayList<>();
if (candidates == null || candidates.length == 0) return rst;
List<Integer> list = new ArrayList<>();
Arrays.sort(candidates);
dfs(rst, list, candidates, target, 0);
return rst;
}
private void dfs(List<List<Integer>> rst, List<Integer> list, int[] candidates, int target, int prev) {
if (target < 0) return;
if (target == 0) {
rst.add(new ArrayList<>(list));
return;
}
for (int i = prev; i < candidates.length; i++) {
list.add(candidates[i]);
dfs(rst, list, candidates, target - candidates[i], i + 1);
list.remove(list.size() - 1);
if (i != 0 && candidates[i] == candidates[i - 1]) { continue; }}
}
Combination Sum iii: https://leetcode.com/problems/combination-sum-iii/#/description
- n, k. no dup in input. can be used only once.
- similar to ii, but without dup
- O(C(k, 9))
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> rst = new ArrayList<>();
if (k == 0) {
return rst;
}
List<Integer> list = new ArrayList<>();
dfs(rst, list, k, n, 1);
return rst;
}
private void dfs(List<List<Integer>> rst, List<Integer> list, int k, int n, int prev) {
if (k == list.size() && n == 0) {
rst.add(new ArrayList<>(list));
}
for (int i = prev; i <= 9; i++) {
list.add(i);
dfs(rst, list, k, n - i, i + 1);
list.remove(list.size() - 1);
}
}
Combination Sum IV: https://leetcode.com/problems/combination-sum-iv/#/description
- input has no dup. can use elements multiple times. different sequence count as different
- total solution count, instead of all possible solutions
- so DP instead of DFS
- memorized search
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 1; i < target + 1; i++) {
for (int num : nums) {
if (i - num >= 0)
dp[i] += dp[i - num];
}
}
return dp[target];
}
}