@ysongzybl
2015-05-24T05:27:00.000000Z
字数 10835
阅读 995
interview
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].
public void dfs(List<List<Integer>> res, int[] nums, ArrayList<Integer> sol, boolean [] visited){if(sol.size() == nums.length){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return ;}for(int i=0; i<nums.length; i++){if(visited[i]) continue;visited[i]=true;sol.add(nums[i]);dfs(res, nums, sol, visited);sol.remove(sol.size()-1);visited[i]=false;}}public List<List<Integer>> permute(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();int n = nums.length;if(n==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();boolean visited [] = new boolean [n];Arrays.sort(nums);dfs(res, nums, sol, visited);return res;}
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].
public void dfs(List<List<Integer>> res, int[] nums, ArrayList<Integer> sol, boolean [] visited){if(sol.size() == nums.length){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return ;}for(int i=0; i<nums.length; i++){if(visited[i]) continue;if(i>0 && nums[i]==nums[i-1] && visited[i-1]) continue; // mistake : must check visitedvisited[i]=true;sol.add(nums[i]);dfs(res, nums, sol, visited);sol.remove(sol.size()-1);visited[i]=false;}}public List<List<Integer>> permuteUnique(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();int n = nums.length;if(n==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();boolean visited [] = new boolean [n];Arrays.sort(nums);dfs(res, nums, sol, visited);return res;}
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],
]
public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int n, int k, int cur){if(sol.size()==k) {List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return;}for(int i=cur; i<=n; i++){sol.add(i);dfs(res, sol, n, k, i+1);sol.remove(sol.size()-1);}}public List<List<Integer>> combine(int n, int k) {List<List<Integer>> res = new ArrayList<List<Integer>>();if(n==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();dfs(res, sol, n, k, 1);return res;}
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.
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]
public class Solution {public void dfs(List<List<Integer>> res, int[] candidates, ArrayList<Integer> sol, int cur_idx, int cur_sum, int target){if(cur_sum==target){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return;}if(cur_idx == candidates.length) return;if(cur_sum>target) return;for(int i=cur_idx; i<candidates.length; i++){sol.add(candidates[i]);dfs(res, candidates, sol, i, cur_sum+candidates[i], target); // use the same numbersol.remove(sol.size()-1);}}public List<List<Integer>> combinationSum2(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<List<Integer>>();int n = candidates.length;if(n==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();Arrays.sort(candidates);dfs(res, candidates, sol, 0, 0, target);return res;}}
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]
public class Solution {public void dfs(List<List<Integer>> res, int[] candidates, ArrayList<Integer> sol, int cur_idx, int cur_sum, int target){if(cur_sum==target){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return;}if(cur_idx == candidates.length) return;if(cur_sum>target) return;for(int i=cur_idx; i<candidates.length; i++){if(i>cur_idx && candidates[i]==candidates[i-1]) continue; // pass duplicatessol.add(candidates[i]);dfs(res, candidates, sol, i+1, cur_sum+candidates[i], target); // pass nextsol.remove(sol.size()-1);}}public List<List<Integer>> combinationSum2(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<List<Integer>>();int n = candidates.length;if(n==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();Arrays.sort(candidates);dfs(res, candidates, sol, 0, 0, target);return res;}}
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.
public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int k, int target, int cur, int cur_sum){if(cur_sum > target || sol.size()>k ) return;if(cur_sum == target && sol.size() == k){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return;}for(int i=cur; i<=9; i++){sol.add(i);dfs(res, sol, k, target, i+1, cur_sum+i);sol.remove(sol.size()-1);}}public List<List<Integer>> combinationSum3(int k, int n) {List<List<Integer>> res = new ArrayList<List<Integer>>();if(k==0|| n<=0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();dfs(res, sol, k, n, 1, 0);return res;}
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,
5/ \4 8/ / \11 13 4/ \ / \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
public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, TreeNode root, int cur_sum, int target){//if(cur_sum>target) return;// mistake when negative node valsif(root==null) return;sol.add(root.val);cur_sum += root.val;if(cur_sum==target && root.left==null && root.right==null){// leaf node checkList<Integer> path = new ArrayList<Integer>(sol);res.add(path);return;}}// can not pass sol directly, in java, sol is an objectArrayList<Integer> sol1 = new ArrayList<Integer>(sol);dfs(res, sol1, root.left, cur_sum, target);ArrayList<Integer> sol2 = new ArrayList<Integer>(sol);dfs(res, sol2, root.right, cur_sum, target);}public List<List<Integer>> pathSum(TreeNode root, int sum) {List<List<Integer>> res = new ArrayList<List<Integer>>();if(root == null) return res;ArrayList<Integer> sol = new ArrayList<Integer>();dfs(res, sol, root, 0, sum);return res;}
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
public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int[] nums, int cur_idx){if(cur_idx == nums.length){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);return;}// pass by current elementdfs(res, sol, nums, cur_idx+1);// add current element to subsetsol.add(nums[cur_idx]);dfs(res, sol, nums, cur_idx+1);sol.remove(sol.size()-1);}public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();if(nums.length==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();Arrays.sort(nums);dfs(res, sol, nums, 0);return res;}
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
public void dfs(List<List<Integer>> res, ArrayList<Integer> sol, int[] nums, int cur_idx){if(!res.contains(sol)){List<Integer> path = new ArrayList<Integer>(sol);res.add(path);// return; // mistake : do not return}for(int i=cur_idx; i<nums.length; i++){sol.add(nums[i]);dfs(res, sol, nums, i+1);sol.remove(sol.size()-1);}}public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();if(nums.length==0) return res;ArrayList<Integer> sol = new ArrayList<Integer>();Arrays.sort(nums);dfs(res, sol, nums, 0);return res;}
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:
[[".Q..", // Solution 1"...Q","Q...","..Q."],["..Q.", // Solution 2"Q...","...Q",".Q.."]]

boolean ok(int[] queens, boolean [] arranged_cols, int row, int col){if(arranged_cols[col]==true) return false;for(int i=0; i<row; i++){if(queens[i] >= 0){if(row-i == Math.abs(queens[i]-col)) return false;}}}return true;}void dfs(List<String[]> boards, int [] queens, boolean[] arranged_cols, int cur_row){int n = queens.length;if(cur_row==n){// generate boardString board[] = new String[n];for(int i=0; i<n; i++){StringBuilder row = new StringBuilder();for(int j=0; j<n; j++){if(j==queens[i]) row.append('Q');else row.append('.');}}board[i] = row.toString();}boards.add(board);return;}for(int col=0; col<n; col++){if(ok(queens, arranged_cols, cur_row, col)){queens[cur_row] = col;arranged_cols[col]=true;dfs(boards, queens, arranged_cols, cur_row+1);arranged_cols[col]=false;queens[cur_row] = -1;}}}public List<String[]> solveNQueens(int n) {List<String[]> boards = new ArrayList<String[]>();if(n==0) return boards;int queens[] = new int[n];Arrays.fill(queens, -1);boolean arranged_cols[] = new boolean[n];dfs(boards, queens, arranged_cols, 0);return boards;}
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
int count = 0;public boolean ok(int [] queens, boolean [] arranged_cols, int cur_row, int cur_col){if(arranged_cols[cur_col]) return false;for(int i=0; i<cur_row; i++){int j = queens[i];if(j>=0){if(Math.abs(j-cur_col) == cur_row - i) return false;}}return true;}public void dfs(int [] queens, boolean [] arranged_cols, int cur_row){if(cur_row==queens.length){count++;return;}// for each un-arranged column, check each row if it is ok to place a queenfor(int j=0; j<queens.length; j++){if(arranged_cols[j]==false){if(ok(queens, arranged_cols, cur_row, j)){queens[cur_row] = j;arranged_cols[j] = true;dfs(queens, arranged_cols, cur_row+1);arranged_cols[j] = false;queens[cur_row] = -1;}}}}public int totalNQueens(int n) {if(n<=1) return n;// arranged_cols[i] = true in column i, there is a queenboolean arranged_cols [] = new boolean [n];// queens[i] = j means the queen i is placed in column jint queens [] = new int [n];Arrays.fill(queens, -1);dfs(queens, arranged_cols, 0);return count;}