1. 程式人生 > >遞歸回溯問題的四道經典題:N皇后,組合,全排列,二叉樹路徑和

遞歸回溯問題的四道經典題:N皇后,組合,全排列,二叉樹路徑和

組合和排列問題的實質是對N叉樹的遍歷,只是退出條件不同。

1.組合

描述:給出兩個整數n和k,返回從1……n中選出的k個數的組合。
樣例:
例如 n = 4 且 k = 2

返回的解為:

[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4]]

public class Solution {
    /**
     * @param n: Given the range of numbers
     * @param k: Given the numbers of combinations
     * @return: All the combinations of k numbers out of 1..n
     */
public List<List<Integer>> combine(int n, int k) { // write your code here List<List<Integer>> res=new ArrayList<>(); List<Integer> solution=new ArrayList<>(); if(n<=0) return res; if(n<k){ return
res; } helper(res,solution,n,k,1); return res; } void helper(List<List<Integer>> res,List<Integer> solution,int n,int k,int start){ if(solution.size()==k){ res.add(new ArrayList<Integer>(solution)); return; } for
(int i=start;i<=n;++i){ solution.add(i); helper(res,solution,n,k,i+1); solution.remove(solution.size()-1); } } }

全排列:

描述:給定一個數字列表,返回其所有可能的排列。
樣例:
給出一個列表[1,2,3],其全排列為:

[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

class Solution {
    /**
     * @param nums: A list of integers.
     * @return: A list of permutations.
     */
    public List<List<Integer>> permute(int[] nums) {
        // write your code here
        ArrayList<List<Integer>> res=new ArrayList<List<Integer>>();
        if(nums==null)
            return res;
        if(nums.length==0){
            res.add(new ArrayList<Integer>());
            return res;
        }
        List<Integer> solution=new ArrayList<>();
        helper(nums,res,solution);
        return res;
    }

    public void helper(int[] nums,List<List<Integer>> res,List<Integer> solution){
        if(solution.size()==nums.length){
            res.add(new ArrayList<Integer>(solution));
            return;
        }
        for(int i=0;i<nums.length;++i){
            if(solution.contains(nums[i])){
                continue;
            }
            solution.add(nums[i]);
            helper(nums,res,solution);
            solution.remove(solution.size()-1);
        }
    }
}

N皇后問題:
描述:
n皇后問題是將n個皇后放置在n*n的棋盤上,皇后彼此之間不能相互攻擊。

給定一個整數n,返回所有不同的n皇后問題的解決方案。

每個解決方案包含一個明確的n皇后放置佈局,其中“Q”和“.”分別表示一個女王和一個空位置。

對於4皇后問題存在兩種解決的方案:
[
    [".Q..", // Solution 1

     "...Q",

     "Q...",

     "..Q."],

    ["..Q.", // Solution 2

     "Q...",

     "...Q",

     ".Q.."]
]
class Solution {
    /**
     * Get all distinct N-Queen solutions
     * @param n: The number of queens
     * @return: All distinct solutions
     * For example, A string '...Q' shows a queen on forth position
     */
    ArrayList<ArrayList<String>> solveNQueens(int n) {
        // write your code here
        ArrayList<ArrayList<String>> res=new ArrayList<ArrayList<String>>();
        if(n<=0){
            return res;
        }
        ArrayList<Integer> cols=new ArrayList<>();
        search(res,cols,n);
        return res;
    }
    public void search(ArrayList<ArrayList<String>> res,ArrayList<Integer> cols,int n){
        if(cols.size()==n){
            res.add(draw(cols));
            return;
        }
        for(int index=0;index<n;++index){
            if(!isSafe(cols,index)){
                continue;
            }
            cols.add(index);
            search(res,cols,n);
            cols.remove(cols.size()-1);
        }
    }
    public ArrayList<String> draw(ArrayList<Integer> cols){
        ArrayList<String> solution=new ArrayList<>();
        for(int i=0;i<cols.size();++i){
            String str="";
            for(int j=0;j<cols.size();++j){
                if(j==cols.get(i)){
                    str=str+"Q";
                }
                else{
                    str=str+".";
                }
            }
            solution.add(str);
        }
        return solution;
    }
    public boolean isSafe(ArrayList<Integer> cols,int colIndex){
        int rowIndex=cols.size();
        for(int row=0;row<cols.size();++row){
            int column=cols.get(row);
            if(column==colIndex){
                return false;
            }
            if(row-column==rowIndex-colIndex){
                return false;
            }
            if(row+column==rowIndex+colIndex){
                return false;
            }
        }
         return true;
    }
};

二叉樹路徑:

描述:
給定一個二叉樹,找出所有路徑中各節點相加總和等於給定 目標值 的路徑。

一個有效的路徑,指的是從根節點到葉節點的路徑。

樣例:

給定一個二叉樹,和 目標值 = 5:

     1
    / \
   2   4
  / \
 2   3
返回:

[
  [1, 2, 2],
  [1, 4]
]
/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     * @param root the root of binary tree
     * @param target an integer
     * @return all valid paths
     */
    public List<List<Integer>> binaryTreePathSum(TreeNode root, int target) {
        // Write your code here
        List<List<Integer>> res=new ArrayList<>();
        List<Integer> path=new ArrayList<>();
        if(root==null){
            return res;
        }
        helper(res,path,root,target);
        return res;

    }
    public void helper(List<List<Integer>> res,List<Integer> path,TreeNode root,int target){
        Boolean isLeaf=root.left==null&&root.right==null;
        if(isLeaf&&target==root.val){
            List<Integer> solution=new ArrayList<>(path);
            solution.add(root.val);
            res.add(solution);
            return;
        }
        path.add(root.val);
        if(root.left!=null){
            helper(res,path,root.left,target-root.val);
        }
        if(root.right!=null){
            helper(res,path,root.right,target-root.val);
        }
        path.remove(path.size()-1);

    }
}