[关闭]
@ysongzybl 2015-05-24T05:27:00.000000Z 字数 10835 阅读 934

Summary: Problems solved with DFS recursions II (NP Problems)

interview


SORT the fucking given array/number set if the output requires ascending order

1. Permutations

Permutations I

Given a collection of numbers, return all possible permutations.

Key:
Mark visited numbers:
if visited, continue to next number;
otherwise, use current number in current permutation, then mark it visited

Example, [1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].

  1. public void dfs(List<List<Integer>> res, int[] nums, ArrayList<Integer> sol, boolean [] visited){
  2. if(sol.size() == nums.length){
  3. List<Integer> path = new ArrayList<Integer>(sol);
  4. res.add(path);
  5. return ;
  6. }
  7. for(int i=0; i<nums.length; i++){
  8. if(visited[i]) continue;
  9. visited[i]=true;
  10. sol.add(nums[i]);
  11. dfs(res, nums, sol, visited);
  12. sol.remove(sol.size()-1);
  13. visited[i]=false;
  14. }
  15. }
  16. public List<List<Integer>> permute(int[] nums) {
  17. List<List<Integer>> res = new ArrayList<List<Integer>>();
  18. int n = nums.length;
  19. if(n==0) return res;
  20. ArrayList<Integer> sol = new ArrayList<Integer>();
  21. boolean visited [] = new boolean [n];
  22. Arrays.sort(nums);
  23. dfs(res, nums, sol, visited);
  24. return res;
  25. }

PermutationsII

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

Example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].

  1. public void dfs(List<List<Integer>> res, int[] nums, ArrayList<Integer> sol, boolean [] visited){
  2. if(sol.size() == nums.length){
  3. List<Integer> path = new ArrayList<Integer>(sol);
  4. res.add(path);
  5. return ;
  6. }
  7. for(int i=0; i<nums.length; i++){
  8. if(visited[i]) continue;
  9. if(i>0 && nums[i]==nums[i-1] && visited[i-1]) continue; // mistake : must check visited
  10. visited[i]=true;
  11. sol.add(nums[i]);
  12. dfs(res, nums, sol, visited);
  13. sol.remove(sol.size()-1);
  14. visited[i]=false;
  15. }
  16. }
  17. public List<List<Integer>> permuteUnique(int[] nums) {
  18. List<List<Integer>> res = new ArrayList<List<Integer>>();
  19. int n = nums.length;
  20. if(n==0) return res;
  21. ArrayList<Integer> sol = new ArrayList<Integer>();
  22. boolean visited [] = new boolean [n];
  23. Arrays.sort(nums);
  24. dfs(res, nums, sol, visited);
  25. return res;
  26. }

2. Combinations

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

For example
If n = 4 and k = 2, a solution is:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

  1. public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int n, int k, int cur){
  2. if(sol.size()==k) {
  3. List<Integer> path = new ArrayList<Integer>(sol);
  4. res.add(path);
  5. return;
  6. }
  7. for(int i=cur; i<=n; i++){
  8. sol.add(i);
  9. dfs(res, sol, n, k, i+1);
  10. sol.remove(sol.size()-1);
  11. }
  12. }
  13. public List<List<Integer>> combine(int n, int k) {
  14. List<List<Integer>> res = new ArrayList<List<Integer>>();
  15. if(n==0) return res;
  16. ArrayList<Integer> sol = new ArrayList<Integer>();
  17. dfs(res, sol, n, k, 1);
  18. return res;
  19. }

3. Combination Sum

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

Combination Sum I

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

For example, given candidate set 2,3,6,7 and target 7,
A solution set is:
[7]
[2, 2, 3]

  1. public class Solution {
  2. public void dfs(List<List<Integer>> res, int[] candidates, ArrayList<Integer> sol, int cur_idx, int cur_sum, int target){
  3. if(cur_sum==target){
  4. List<Integer> path = new ArrayList<Integer>(sol);
  5. res.add(path);
  6. return;
  7. }
  8. if(cur_idx == candidates.length) return;
  9. if(cur_sum>target) return;
  10. for(int i=cur_idx; i<candidates.length; i++){
  11. sol.add(candidates[i]);
  12. dfs(res, candidates, sol, i, cur_sum+candidates[i], target); // use the same number
  13. sol.remove(sol.size()-1);
  14. }
  15. }
  16. public List<List<Integer>> combinationSum2(int[] candidates, int target) {
  17. List<List<Integer>> res = new ArrayList<List<Integer>>();
  18. int n = candidates.length;
  19. if(n==0) return res;
  20. ArrayList<Integer> sol = new ArrayList<Integer>();
  21. Arrays.sort(candidates);
  22. dfs(res, candidates, sol, 0, 0, target);
  23. return res;
  24. }
  25. }

Combination Sum II

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

For example, given candidate set 10,1,2,7,6,1,5 and target 8,
A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]

  1. public class Solution {
  2. public void dfs(List<List<Integer>> res, int[] candidates, ArrayList<Integer> sol, int cur_idx, int cur_sum, int target){
  3. if(cur_sum==target){
  4. List<Integer> path = new ArrayList<Integer>(sol);
  5. res.add(path);
  6. return;
  7. }
  8. if(cur_idx == candidates.length) return;
  9. if(cur_sum>target) return;
  10. for(int i=cur_idx; i<candidates.length; i++){
  11. if(i>cur_idx && candidates[i]==candidates[i-1]) continue; // pass duplicates
  12. sol.add(candidates[i]);
  13. dfs(res, candidates, sol, i+1, cur_sum+candidates[i], target); // pass next
  14. sol.remove(sol.size()-1);
  15. }
  16. }
  17. public List<List<Integer>> combinationSum2(int[] candidates, int target) {
  18. List<List<Integer>> res = new ArrayList<List<Integer>>();
  19. int n = candidates.length;
  20. if(n==0) return res;
  21. ArrayList<Integer> sol = new ArrayList<Integer>();
  22. Arrays.sort(candidates);
  23. dfs(res, candidates, sol, 0, 0, target);
  24. return res;
  25. }
  26. }

Combination Sum III

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

Example 1:
Input: k = 3, n = 7
Output: [[1,2,4]]

Example 2:
Input: k = 3, n = 9
Output: [[1,2,6], [1,3,5], [2,3,4]]

Idea:
Similar to combination I and II, just modify different termination condition.

  1. public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int k, int target, int cur, int cur_sum){
  2. if(cur_sum > target || sol.size()>k ) return;
  3. if(cur_sum == target && sol.size() == k){
  4. List<Integer> path = new ArrayList<Integer>(sol);
  5. res.add(path);
  6. return;
  7. }
  8. for(int i=cur; i<=9; i++){
  9. sol.add(i);
  10. dfs(res, sol, k, target, i+1, cur_sum+i);
  11. sol.remove(sol.size()-1);
  12. }
  13. }
  14. public List<List<Integer>> combinationSum3(int k, int n) {
  15. List<List<Integer>> res = new ArrayList<List<Integer>>();
  16. if(k==0|| n<=0) return res;
  17. ArrayList<Integer> sol = new ArrayList<Integer>();
  18. dfs(res, sol, k, n, 1, 0);
  19. return res;
  20. }

5. Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.

Example: Given the below binary tree and sum = 22,

  1. 5
  2. / \
  3. 4 8
  4. / / \
  5. 11 13 4
  6. / \ / \
  7. 7 2 5 1

return
[
[5,4,11,2],
[5,8,4,5]
]

Idea:
sum values of nodes from root to leaf, add to results if sum target number

  1. public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, TreeNode root, int cur_sum, int target){
  2. //if(cur_sum>target) return;
  3. // mistake when negative node vals
  4. if(root==null) return;
  5. sol.add(root.val);
  6. cur_sum += root.val;
  7. if(cur_sum==target && root.left==null && root.right==null){
  8. // leaf node check
  9. List<Integer> path = new ArrayList<Integer>(sol);
  10. res.add(path);
  11. return;
  12. }
  13. }
  14. // can not pass sol directly, in java, sol is an object
  15. ArrayList<Integer> sol1 = new ArrayList<Integer>(sol);
  16. dfs(res, sol1, root.left, cur_sum, target);
  17. ArrayList<Integer> sol2 = new ArrayList<Integer>(sol);
  18. dfs(res, sol2, root.right, cur_sum, target);
  19. }
  20. public List<List<Integer>> pathSum(TreeNode root, int sum) {
  21. List<List<Integer>> res = new ArrayList<List<Integer>>();
  22. if(root == null) return res;
  23. ArrayList<Integer> sol = new ArrayList<Integer>();
  24. dfs(res, sol, root, 0, sum);
  25. return res;
  26. }

6. Subsets

Subsets I

Given a set of distinct integers, nums, return all possible subsets.

Note:
Elements in a subset must be in non-descending order.
The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

Idea:
For each number i in the given set, we can form a subset with or without it.

  1. public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int[] nums, int cur_idx){
  2. if(cur_idx == nums.length){
  3. List<Integer> path = new ArrayList<Integer>(sol);
  4. res.add(path);
  5. return;
  6. }
  7. // pass by current element
  8. dfs(res, sol, nums, cur_idx+1);
  9. // add current element to subset
  10. sol.add(nums[cur_idx]);
  11. dfs(res, sol, nums, cur_idx+1);
  12. sol.remove(sol.size()-1);
  13. }
  14. public List<List<Integer>> subsets(int[] nums) {
  15. List<List<Integer>> res = new ArrayList<List<Integer>>();
  16. if(nums.length==0) return res;
  17. ArrayList<Integer> sol = new ArrayList<Integer>();
  18. Arrays.sort(nums);
  19. dfs(res, sol, nums, 0);
  20. return res;
  21. }

Subsets II

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

  1. public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int[] nums, int cur_idx){
  2. if(!res.contains(sol)){
  3. List<Integer> path = new ArrayList<Integer>(sol);
  4. res.add(path);
  5. // return; // mistake : do not return
  6. }
  7. for(int i=cur_idx; i<nums.length; i++){
  8. sol.add(nums[i]);
  9. dfs(res, sol, nums, i+1);
  10. sol.remove(sol.size()-1);
  11. }
  12. }
  13. public List<List<Integer>> subsets(int[] nums) {
  14. List<List<Integer>> res = new ArrayList<List<Integer>>();
  15. if(nums.length==0) return res;
  16. ArrayList<Integer> sol = new ArrayList<Integer>();
  17. Arrays.sort(nums);
  18. dfs(res, sol, nums, 0);
  19. return res;
  20. }

7. N Queens

N Queens I

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

Example, there exist two distinct solutions to the 4-queens puzzle:

  1. [
  2. [".Q..", // Solution 1
  3. "...Q",
  4. "Q...",
  5. "..Q."],
  6. ["..Q.", // Solution 2
  7. "Q...",
  8. "...Q",
  9. ".Q.."]
  10. ]

  1. boolean ok(int[] queens, boolean [] arranged_cols, int row, int col){
  2. if(arranged_cols[col]==true) return false;
  3. for(int i=0; i<row; i++){
  4. if(queens[i] >= 0){
  5. if(row-i == Math.abs(queens[i]-col)) return false;
  6. }
  7. }
  8. }
  9. return true;
  10. }
  11. void dfs(List<String[]> boards, int [] queens, boolean[] arranged_cols, int cur_row){
  12. int n = queens.length;
  13. if(cur_row==n){
  14. // generate board
  15. String board[] = new String[n];
  16. for(int i=0; i<n; i++){
  17. StringBuilder row = new StringBuilder();
  18. for(int j=0; j<n; j++){
  19. if(j==queens[i]) row.append('Q');
  20. else row.append('.');
  21. }
  22. }
  23. board[i] = row.toString();
  24. }
  25. boards.add(board);
  26. return;
  27. }
  28. for(int col=0; col<n; col++){
  29. if(ok(queens, arranged_cols, cur_row, col)){
  30. queens[cur_row] = col;
  31. arranged_cols[col]=true;
  32. dfs(boards, queens, arranged_cols, cur_row+1);
  33. arranged_cols[col]=false;
  34. queens[cur_row] = -1;
  35. }
  36. }
  37. }
  38. public List<String[]> solveNQueens(int n) {
  39. List<String[]> boards = new ArrayList<String[]>();
  40. if(n==0) return boards;
  41. int queens[] = new int[n];
  42. Arrays.fill(queens, -1);
  43. boolean arranged_cols[] = new boolean[n];
  44. dfs(boards, queens, arranged_cols, 0);
  45. return boards;
  46. }

N Queens II

Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.

Idea:
queens[i]=j => at row i, col j, there is a queen
arranged_cols[i]=true => col i has been placed a queen
for each un-arranged column, iterate each row to check if OK to place a queue

  1. int count = 0;
  2. public boolean ok(int [] queens, boolean [] arranged_cols, int cur_row, int cur_col){
  3. if(arranged_cols[cur_col]) return false;
  4. for(int i=0; i<cur_row; i++){
  5. int j = queens[i];
  6. if(j>=0){
  7. if(Math.abs(j-cur_col) == cur_row - i) return false;
  8. }
  9. }
  10. return true;
  11. }
  12. public void dfs(int [] queens, boolean [] arranged_cols, int cur_row){
  13. if(cur_row==queens.length){
  14. count++;
  15. return;
  16. }
  17. // for each un-arranged column, check each row if it is ok to place a queen
  18. for(int j=0; j<queens.length; j++){
  19. if(arranged_cols[j]==false){
  20. if(ok(queens, arranged_cols, cur_row, j)){
  21. queens[cur_row] = j;
  22. arranged_cols[j] = true;
  23. dfs(queens, arranged_cols, cur_row+1);
  24. arranged_cols[j] = false;
  25. queens[cur_row] = -1;
  26. }
  27. }
  28. }
  29. }
  30. public int totalNQueens(int n) {
  31. if(n<=1) return n;
  32. // arranged_cols[i] = true in column i, there is a queen
  33. boolean arranged_cols [] = new boolean [n];
  34. // queens[i] = j means the queen i is placed in column j
  35. int queens [] = new int [n];
  36. Arrays.fill(queens, -1);
  37. dfs(queens, arranged_cols, 0);
  38. return count;
  39. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注