Loading

LeetCode-Backtracking

17. Letter Combinations of a Phone Number 电话号码的字母组合

https://leetcode.com/problems/letter-combinations-of-a-phone-number/

题目:如果字符串包含来自2-9的数字,则返回数字可以表示的所有可能的字母组合。数字到字母的映射(就像在电话按钮上一样)如下所示。注意,1不映射到任何字母。

思路:

class Solution {
    private static final String[] KEYS = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
    
    public List<String> letterCombinations(String digits) {
        List<String> res = new LinkedList<String>();
        if(digits.equals("")) return res;
        combination("", digits, 0, res);
        return res;
    }

    private void combination(String prefix, String digits, int offset, List<String> res) {
        if (offset >= digits.length()) {
            res.add(prefix);
            return;
        }
        String letters = KEYS[(digits.charAt(offset) - '0')];
        for (int i = 0; i < letters.length(); i++) {
            combination(prefix + letters.charAt(i), digits, offset + 1, res);
        }
    }
}
View Code

22. Generate Parentheses 生成括号

https://leetcode.com/problems/generate-parentheses/

题目:给定n对括号,编写一个函数来生成所有格式正确的括号的组合。

思路:

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        generater(n, n, "", res);
        return res;
    }
    
    public void generater(int left, int right, String s, List<String> res) {
        if(left > right) return;
        
        if(left > 0) {
            generater(left-1, right, s + "(", res);
        }
        if(right > 0) {
            generater(left, right-1, s + ")", res);
        }

        if(left == 0 && right == 0) {
            res.add(s);
            return;
        }
    }
}
View Code

37. Sudoku Solver 解答数独

https://leetcode.com/problems/sudoku-solver/

题目:编写一个程序,通过填充空单元格来解决数独难题。

思路:

39. Combination Sum 数字组合之和

https://leetcode.com/problems/combination-sum/

题目:给定一组候选数字(无重复项)和一个目标数字(目标),在候选数字中寻找和为目标数字的候选数字的唯一组合。数字可以重复选择。

思路:

class Solution {
    private List<List<Integer>> res;

    private List<Integer> cur;

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        res = new ArrayList<List<Integer>>();
        cur = new ArrayList<Integer>();
        helper(candidates, target, 0); 
        return res;
    }

    private void helper(int[] candidates, int target, int i) {
        for(int n : cur) {
            System.out.print(n + " ");
        }
        System.out.println();
        if (target == 0) {
            res.add(new ArrayList<>(cur));
        } else if (target < 0) {
            return;
        } else {
            while (i < candidates.length) {
                // i -> lastIndex
                int candidate = candidates[i];
                cur.add(candidate);
                helper(candidates, target - candidate, i);
                cur.remove(cur.size() - 1);
                i++;
            }
        }
    }
}
View Code

40. Combination Sum II

https://leetcode.com/problems/combination-sum-ii/

题目:给定候选人编号(候选人)和目标号码(目标)的集合,在候选人号码之和为目标的候选人中查找所有唯一的组合。候选人中的每个数字只能在组合中使用一次。注:所有数字(包括目标)都是正整数。解决方案集不能包含重复的组合。

思路:

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Arrays.sort(candidates);
        helper(res, new ArrayList<Integer>(), candidates, target, 0); 
        return res;
    }

    private void helper(List<List<Integer>> res, List<Integer> cur, int[] candidates, int target, int start) {
        System.out.println();
        if (target == 0) {
            res.add(new ArrayList<>(cur));
        } else if (target < 0) {
            return;
        } else {
            for (int i = start; i < candidates.length; i++) {
                if(i > start && candidates[i] == candidates[i-1]) {
                    /** skip duplicates */
                    continue;
                }
                int candidate = candidates[i];
                cur.add(candidate);
                helper(res, cur, candidates, target - candidate, i+1);
                cur.remove(cur.size() - 1);
            }
        }
    }
}
View Code

46. Permutations 排列

https://leetcode.com/problems/permutations/

题目:给定一个不同整数集合,返回所有可能的排列。

思路:

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> init = new ArrayList<>();
        for(int i = 0; i < nums.length; i++) {
            init.add(nums[i]);
        }
        permutation(init, new ArrayList<>(), res);
        return res;
    }
    
    private void permutation(List<Integer> init, List<Integer> list, List<List<Integer>> res) {
        if(init.isEmpty()) {
            res.add(new ArrayList<>(list));
        } else {
            for (int i = 0; i < init.size(); i++) {
                List<Integer> initD = new ArrayList<>(init);
                List<Integer> listD = new ArrayList<>(list);
                listD.add(initD.get(i));
                initD.remove(i);
                permutation(initD, listD, res);
            }
        }
    }
}
View Code

47. Permutations II 排列 II

https://leetcode.com/problems/permutations-ii/

题目:给定可能包含重复项的数字集合,则返回所有可能的唯一排列。

思路:

class Solution {   
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if(nums==null || nums.length==0) return res;
        boolean[] used = new boolean[nums.length];
        List<Integer> list = new ArrayList<Integer>();
        Arrays.sort(nums);
        dfs(nums, used, list, res);
        return res;
    }

    public void dfs(int[] nums, boolean[] used, List<Integer> list, List<List<Integer>> res){
        if(list.size()==nums.length){
            res.add(new ArrayList<Integer>(list));
            return;
        }
        for(int i=0;i<nums.length;i++){
            if(used[i]) continue;
            if(i>0 &&nums[i-1]==nums[i] && !used[i-1]) continue;
            used[i]=true;
            list.add(nums[i]);
            dfs(nums,used,list,res);
            used[i]=false;
            list.remove(list.size()-1);
        }
    }
}
View Code

51. N-Queens N皇后问题

https://leetcode.com/problems/n-queens/

题目:在n×n棋盘上放置n个皇后,使得不会有两个皇后能够互相攻击的情况出现。

思路:

class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> result = new ArrayList<>();
        char[][] board = new char[n][n];
        for (int i=0; i<n; i++) {
            for (int j=0; j<n; j++) {
                board[i][j] = '.';
            }
        }
        solveNQueens(n, 0, new int[n], board, result);
        return result;
    }
    
    public void solveNQueens(int n, int row, int[] occupied, char[][] board, List<List<String>> result) {
        // our goal
        if(row == n) {
            List<String> path = new ArrayList<>();
            for (int i=0; i<n; i++) {
                path.add(String.valueOf(board[i]));
            }
            result.add(path);
            // return;
        } else {
            for(int col = 0; col < n; col++) {
                // our choice
                occupied[row] = col;
                board[row][col] = 'Q';
                // our constraints
                if(isValid(occupied, row, col)) {
                    solveNQueens(n, row+1, occupied, board, result);
                }
                // undo our choice
                board[row][col] = '.';
            }
        }
    }
    
    public boolean isValid(int[] occupied, int row, int col) {
        for(int i = 0; i < row; i++) {
            if (occupied[i] == col || Math.abs(col - occupied[i]) == Math.abs(i - row)) {
                return false;
            }
        }
        return true;
    }
}
View Code

52. N-Queens II N皇后问题 II

https://leetcode.com/problems/n-queens-ii/

题目:n皇后之谜是在n×n棋盘上放置n个皇后的问题,这样就不会有两个皇后互相攻击。

思路:

class Solution {
    public int totalNQueens(int n) {
        List<Integer> result = new ArrayList<>();
        solveNQueens(new ArrayList<>(), result, n);
        return result.size();
    }
    
    public void solveNQueens(List<Integer> cur, List<Integer> result, int n) {
        // our goal
        if(cur.size() == n) {
            result.add(1);
            // return;
        }
        for(int col = 0; col < n; col++) {
            if (!cur.contains(col)) {
                if (isValid(cur, col)) {
                    continue;
                }
                cur.add(col);
                solveNQueens(cur, result, n);
                cur.remove(cur.size() - 1);
            }
        }
    }
    
    public boolean isValid(List<Integer> cur, int i) {
        int cur_row = cur.size();
        int cur_col = i;
        for (int row = 0; row < cur.size(); row++) {
            if (Math.abs(cur_row - row) == Math.abs(cur_col - cur.get(row))) {
                return true;
            }
        }
        return false;
    }
}
View Code

77. Combinations 组合

https://leetcode.com/problems/combinations/

题目:给定两个整数n和k,从1中返回所有可能的k数组合。n.

思路:

class Solution {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> res = new ArrayList<>();
        helper(n, k, new ArrayList<>(), res, 1);
        return res;
    }
    
    public void helper(int n, int k, List<Integer> list, List<List<Integer>> res, int start) {
        if(k == 0) {
            res.add(new ArrayList<>(list));
            return;
        }
        for(int i = start; i <= n; i++) {
            list.add(i);
            helper(n, k-1, list, res, i+1); // 注意是i+1不是start+1,不然在第一层递归从2开始循环时start仍为1
            list.remove(list.size()-1);
        }
    }
}
View Code

131. Palindrome Partitioning 将字符串分割成回文

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

 题目:给定字符串s,分区的每个子字符串都是回文。返回s的所有可能的回文分区。

思路:注意 i 从 1 开始,到 s.length() 结束。

class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> res = new ArrayList<>();
        if(s == null || s.length() == 0) return res;
        partitioning(s, new ArrayList<>(), res);
        return res;
    }
    
    public void partitioning(String s, List<String> step, List<List<String>> res) {
        // Base case
        if(s == null || s.length() == 0) {
            res.add(new ArrayList<>(step));
            return;
        }
        for(int i = 1; i <= s.length(); i++) {
            String temp = s.substring(0, i);
            if(!isPalindrome(temp)) continue; // only do backtracking when current string is palindrome
            step.add(temp); // make a choose
            partitioning(s.substring(i, s.length()), step, res); // explore
            step.remove(step.size() - 1); // undo our choose
        }
        return;
    }
    
    public boolean isPalindrome(String s) {
        int left = 0, right = s.length() - 1;
        while(left <= right) {
            if(s.charAt(left) != s.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}
View Code

 

posted @ 2019-10-04 21:07  brynchen  阅读(165)  评论(0)    收藏  举报