Leetcode笔记——回溯

1. 括号生成

2. 组合总和

3. 字符串的全排列(带重复)

1. 括号生成

输入:n = 3
输出:[
       "((()))",
       "(()())",
       "(())()",
       "()(())",
       "()()()"
     ]
---------------------------------------------------------
class Solution {

    List<String> list;

    public List<String> generateParenthesis(int n) {
        list = new ArrayList<>();
        if(n <= 0)      return list;
        dfs("",0,0,n);
        return list;
    }

//left表示已经用了多少(,right表示已经用了多少)
    public void dfs(String string, int left, int right, int n){
        if(left == n && right == n){    //左右括号都用完,添加
            list.add(string);
            return;
        }
        if(left > n || right >n)    return;    //剪枝,左括号或者右括号超标了
        if(right > left)    return;    //右>左,比如 (())),显然不可以,剪枝
        else if(left == right){
            dfs(string+"(" ,left+1, right, n);    //相等时候,只能+(
        }
        else{
            dfs(string+"(" ,left+1, right, n);    其余情况,两个都要试
            dfs(string+")" ,left, right+1, n);
        }
    }
}

2. 组合总和

输入:candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]
-------------------------------------------------------------------
class Solution {

    List<List<Integer>> ans;

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        ans = new ArrayList<>();
        if(candidates.length ==0)   return  ans;
        List<Integer> list = new ArrayList<>();
        Arrays.sort(candidates);
        dfs(list, candidates, 0, target, 0);
        return ans;
    }


//sum表示目前的总和
//start用来记录index防止重复,比如[2,3,4],target=5那么每次找完2开头的之后,下次只能从3开始找,不然会出现[2,3],[3,2]的重复情况

    public void dfs(List<Integer> list, int[] candidates, int sum, int target, int start){
        int length = candidates.length;
        for(int i =start; i<length; i++){
            if(sum + candidates[i] > target)    break;    //已经超过sum,剪枝
            else if(sum + candidates[i] == target){    //正好相等,加入ans
                list.add(candidates[i]);
                ans.add(new ArrayList<Integer>(list));
                list.remove(list.size()-1);
                break;
            }
            else{
                sum += candidates[i];
                list.add(candidates[i]);
                dfs(list, candidates, sum, target, i);    //这里的start =i,下次从后面找,避免重复
                list.remove(list.size()-1);
                sum -= candidates[i];    //sum别忘了减
            }
        }
    }
}

3. 字符串的全排列(带重复)

输入:s = "abcc"
输出:["abcc","acbc","accb","bacc","bcac","bcca","cbac","cbca","cabc","cacb","ccab","ccba"]
------------------------------------------------------------------
思路:回溯
class Solution {

    List<String> list;

    public String[] permutation(String s) {
       int len = s.length();
       if(len == 0)     return new String[0];
       if(len == 1)     return new String[]{s};
       list = new ArrayList<>();
       backtrace(new StringBuilder(s), 0);
       String[] ans = new String[list.size()];
       for(int i =0; i< list.size(); i++){
           ans[i] = list.get(i);
       }
       return ans;
    }  

    public void backtrace(StringBuilder sb, int start){
        int length = sb.length();
        if(start +1 == length){
            list.add(sb.toString());
            return;
        }
        Set<Character> set = new HashSet<>();
        //Set用来记录重复的
        //比如start = 1,sb="abcdcdc"
        //此时只有三种选择 ab开头,ac开头,ad开头
        for(int i = start; i< length; i++){
            char a = sb.charAt(i);
            char b = sb.charAt(start);
            if(set.contains(a))     continue;
            else{
                set.add(a);
            }
            sb.setCharAt(start,a);
            sb.setCharAt(i,b);
            backtrace(sb, start+1);
            sb.setCharAt(start,b);
            sb.setCharAt(i,a);
        }
        return;

    } 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值