关闭

[置顶] [编程题] LeetCode上的backTracking类型的题目-难度Medium

标签: leetcode编程
221人阅读 评论(0) 收藏 举报
分类:

最近把LeetCode上的backTracking的题目做了一下,发现都是一个套路~
backTracking链接:https://leetcode.com/tag/backtracking/
还有几道比较难的Medium的题和Hard的题没做出来,后面会继续更新和加详细解法解释~


回溯的入门之子集-Subsets

这种题目都是使用这个套路,就是用一个循环去枚举当前所有情况,然后把元素加入,递归,再把元素移除
按照这个套路来做,可以解决backTracking的问题

public class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        backTracking(res, new ArrayList<>(), nums, 0);
        return res;
    }

    private void backTracking(List<List<Integer>> res, List<Integer> list, int[] nums, int start){

        res.add(new ArrayList<>(list)); //第一步 满足条件的临时集合加入结果集

        for(int i = start; i < nums.length; ++i){ //第二步for循环 遍历所有的元素

            list.add(nums[i]); //第三步 元素加入临时集合

            backTracking(res, list, nums, i + 1); //第四步 回溯

            list.remove(list.size() - 1); //第五步 元素从临时集合移除

        }
    }
}

Subsets II

返回数组(里面有重复的数字)的不含重复结果的子集

public class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        backTracking(res, new ArrayList<>(), nums, 0);
        return res;
    }

    private void backTracking(List<List<Integer>> res, List<Integer> list, int[] nums, int start){
        if(!res.contains(list)) res.add(new ArrayList<>(list)); //检查是否包含结果,不包含才加入
        for(int i = start; i < nums.length; ++i){
            list.add(nums[i]);
            backTracking(res, list, nums, i + 1);
            list.remove(list.size() - 1);
        }
    }
}

Letter Combinations of a Phone Number

手机键盘拨号,给你一串数字,问对应手机九宫格的输入法有可能输出那些字符串。

手机键盘:
这里写图片描述

输入:

“23”

输出:

[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]

public class Solution {
    private String[] letter = new String[] {" ", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public List<String> letterCombinations(String digits) {
        List<String> res = new ArrayList<>();
        if(digits == null || digits.length() == 0) return res;
        char[] nums = digits.toCharArray();
        backTracking(res, new StringBuilder(), nums, 0);
        return res;
    }

    private void backTracking(List<String> res, StringBuilder build, char[] nums, int start){
        if(build.length() == nums.length) res.add(build.toString());
        for(int i = start; i < nums.length; ++i){
            int index = Integer.parseInt(String.valueOf(nums[i]));
            for(int j = 0; j < letter[index].length(); ++j){
                build.append(letter[index].charAt(j));
                backTracking(res, build, nums, i + 1);
                build.deleteCharAt(build.length() - 1);
            }
        }
    }
}

Generate Parentheses 括号生成器

public class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        backTracking(res, new StringBuilder(), 0, 0, n);
        return res;
    }

    private void backTracking(List<String> res, StringBuilder builder, int left, int right, int n){
        if(builder.length() == n*2) res.add(builder.toString());
        else {
            if(left < n){ 
                builder.append("(");
                backTracking(res, builder, left+1, right, n);
                builder.deleteCharAt(builder.length()-1);
            }
            if(right < n && left > right){
                builder.append(")");
                backTracking(res, builder, left, right+1, n);
                builder.deleteCharAt(builder.length()-1);
            }

        } 
    }
}

Combinations

给你两个整数n和k,返回在1到n个数里面所有可能的k个数字的组合。

public class Solution {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> res = new ArrayList<>();
        backTracking(res, new ArrayList<>(), n, k, 1);
        return res;
    }

    private void backTracking(List<List<Integer>> res, List<Integer> list, int n, int k, int start){
        if(list.size() == k) res.add(new ArrayList(list));
        for(int i = start; i <= n; ++i){
            list.add(i);
            backTracking(res, list, n, k, i + 1);
            list.remove(list.size() - 1);
        }
    }
}

Combination Sum

给定一个数组candidates,和一个整数target,返回所有candidates里面元素的组合的和等于target。对candidates里面的元素出现的次数无限制。

例如:

candidate : [2, 3, 6, 7] | target: 7

返回:

这里写图片描述

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

    private void backTracking(List<List<Integer>> res, List<Integer> list, int[] candidate, int target, int start){
        if(target < 0) return;
        if(target == 0) res.add(new ArrayList<>(list));
        else {
            for(int i = start; i < candidate.length; ++i){
                list.add(candidate[i]);
                backTracking(res, list, candidate, target - candidate[i], i);
                list.remove(list.size() - 1);
            }
        }
    }
}

Combination Sum II

给定一个数组candidates,和一个整数target,返回所有candidates里面元素的组合的和等于target。对candidates里面的元素最多只能出现一次。

例如:

candidate : [10, 1, 2, 7, 6, 1, 5]
target: 8

返回:

这里写图片描述

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

    private void backTracking(List<List<Integer>> res, List<Integer> list, int[] candidate, int target, int start){
        if(target < 0) return;
        if(target == 0) res.add(new ArrayList<>(list));
        else {
            for(int i = start; i < candidate.length; ++i){
                if(i > start && candidate[i] == candidate[i - 1]) continue;
                list.add(candidate[i]);
                backTracking(res, list, candidate, target - candidate[i], i + 1);
                list.remove(list.size() - 1);
            }
        }
    }
}

Combination Sum III

public class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> res = new ArrayList<>();
        backTracking(res, new ArrayList<>(), k, n, 1);
        return res;
    }

    private void backTracking(List<List<Integer>> res, List<Integer> list, int k, int n, int start){
        if(n < 0) return;
        if(n == 0 && list.size() == k) res.add(new ArrayList<>(list));
        for(int i = start; i <= 9; i++){
            list.add(i);
            backTracking(res, list, k, n-i, i+1);
            list.remove(list.size()-1);
        }
    }
}

Permutations 排列

给你一个数字不重复的数组,求这个数组的所有排列

public class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        backTracking(res, new ArrayList<>(), nums);
        return res;
    }

     private void backTracking(List<List<Integer>> res, List<Integer> list, int[] nums){
        if(list.size() == nums.length) res.add(new ArrayList<>(list));
        for(int i = 0; i < nums.length; ++i){
            if(list.contains(nums[i])) continue; // 跳过重复的
            list.add(nums[i]);
            backTracking(res, list, nums);
            list.remove(list.size() - 1);
        }
    }
}

Palindrome Partitioning 分割回文字串

给你一个字符串s,分割字符串s使得每个子字符串都是回文,返回所有的分割结果。

如s = “aab”
返回:
[
[“aa”,”b”],
[“a”,”a”,”b”]
]

public class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> res = new ArrayList<>();
        backTracking(res, new ArrayList<>(), s, 0);
        return res;
    }

    private void backTracking(List<List<String>> res, List<String> list, String s, int start){
        if(start == s.length()) res.add(new ArrayList<>(list)); //start == s.length()的时候,说明已经带s的最后一个字符了
        else {
            for(int i = start; i < s.length(); i++){
                if(isPalindrome(s, start, i)){
                    list.add(s.substring(start, i+1));
                    backTracking(res, list, s, i+1);
                    list.remove(list.size() - 1);
                }
            }
        }
    }

    /*
     * 判断是否是回文
     */
    private boolean isPalindrome(String s, int low, int high){
        while(low < high){
            if(s.charAt(low++) != s.charAt(high--)) return false;
        }
        return true;
    }
}

N-Queens

有了 Palindrome Partitioning 分割回文字串 的基础,我们就可以解决经典的 N-皇后 的问题了: N-Queens

设计一种算法,打印n皇后在n*n棋盘上的各种摆法,其中每个皇后都不同行,不同列,也不在对角线上。

public class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<Integer[]> res = new ArrayList<>();
        backTracking(res, new Integer[n], n, 0);

        //以下只是把皇后放置在棋盘上
        List<List<String>> resList = new ArrayList<>();
        for(Integer[] nums: res){
            List<String> list = new ArrayList<>();
            for(int i = 0; i < nums.length; i++){
                StringBuilder sb = new StringBuilder();
                for(int j = 0; j < n; j++){
                    if(j == nums[i]) sb.append("Q");
                    else sb.append(".");
                }
                list.add(sb.toString());
            }
            resList.add(list);
        }
        return resList;
    }

    /*
     * queen[] 是表示:下表i代表第i行的第queen[i]列放置一个皇后
     */
    private void backTracking(List<Integer[]> res, Integer[] queen, int n, int start){
        if(start == n) res.add(queen.clone());
        else {
            for(int i = 0; i < n; i++){ //不是从start开始
                if(checkValid(queen, start, i)){
                    queen[start] = i;
                    backTracking(res, queen, n, start+1); //不是i+1,i只是和列有关
                }
            }
        }

    }

    /*
     * 检查在位置(row1,col1)是否可以放置皇后
     */
    private boolean checkValid(Integer[] queen, int row1, int col1){
        for(int row2 = 0; row2 < row1; row2++){
            int col2 = queen[row2];
            if(col2 == col1) return false; //两个皇后放置在同一列上
            int colSize = Math.abs(col1 - col2);
            int rowSize = row1 - row2;
            if(colSize == rowSize) return false; //两个皇后放置在同一对角线上
        }
        return true;
    }
}
2
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:8102次
    • 积分:356
    • 等级:
    • 排名:千里之外
    • 原创:25篇
    • 转载:1篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论