首页 > 其他分享 >回溯

回溯

时间:2022-11-07 22:11:43浏览次数:51  
标签:nums int res 回溯 startIndex new path

for循环横向遍历,递归纵向遍历,回溯不断调整结果集
画树,回溯要画树

77. 组合

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。

result.add(new ArrayList(path)):开辟一个独立地址,地址中存放的内容为path链表,后续path的变化不会影响到res

res.add(path):将res尾部指向了path地址,后续path内容的变化会导致res的变化。

class Solution {
    LinkedList<Integer> path = new LinkedList<>();
    List<List<Integer>> result = new ArrayList<>();

    public List<List<Integer>> combine(int n, int k) {
        backTracking(n,k,1);
        return result;
    }

    void backTracking(int n, int k, int startIndex){
        if(path.size()==k){
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = startIndex; i <= n; i++) {
            path.add(i);
            backTracking(n,k,i+1);
            path.removeLast();//回溯
        }
    }
}

剪枝操作优化代码:

for (int i = startIndex; i <= n; i++) {

剪枝:

for (int i = startIndex; i <=n-(k-path.size())+1; i++) {

path.size() 是当前路径里元素的个数
k-path.size() 是还需要的元素个数
n-(k-path.size())+1 至多走到哪里



216. 组合总和 III

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次 
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

  • 这题和上面一题十分相似,就浅浅改了一下上面的代码
class Solution {

     LinkedList<Integer> path = new LinkedList<>();
     List<List<Integer>> result = new ArrayList<>();

    public  List<List<Integer>> combinationSum3(int k, int n) {
        if(k > n){//如果n小于k的话直接返回
            return result;
        }
        backTracking(k,n,1);
        return result;
    }

     void backTracking(int k, int n, int startIndex){

        if(path.size()==k){//数组的长度达到标准之后
            int sum = 0;
            for (Integer p : path) {
                sum +=p;
            }
            if(sum == n){//看数组中数字之和是否达到标准
                result.add(new ArrayList<>(path));
            }
            return;
        }
        for (int i = startIndex; i <= n; i++) {
            path.add(i);
            backTracking(k,n,i+1);
            path.removeLast();
        }
    }
}
  • 结果超出时间限制,因为没有剪枝
for (int i = startIndex; i <= Math.min(n-(k*(k-1)/2),9) ; i++) {
  • k*(k-1)/2 是对前k-1个数的求和
  • n-(k*(k-1)/2) 和 9 取最小是怕n太大,k太小导致path里的数 > 9


17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

  • 把按键上对应的数字转换成字符串letters,遍历的时候要遍历的是字符串
class Solution {

     List<String> result = new ArrayList<>();
    static String[] letters = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};//下标就是按键上的数字

    public List<String> letterCombinations(String digits) {
        if(digits.equals(""))
             return result;//对特殊情况特殊处理
        backTracking(digits,0);//从零开始
        return result;
    }

    static StringBuilder sb = new StringBuilder();
    
     void backTracking(String digits, int index){
         //index指的是当前对哪个数字进行处理
         if(sb.length()==digits.length()){
            result.add(sb.toString());
            return;
         }
        String letter = letters[(digits.charAt(index))-'0'];//取当前下标对应的字符串
        for (int i = 0; i < letter.length(); i++) {
            sb.append(letter.charAt(i));
            backTracking(digits,index+1);
            sb.deleteCharAt(sb.length()-1);
        }
    }
}

相关文章

  • 代码随想录训练营第二十五天 | 回溯算法
    今天是第二十五天,回溯算法216.组合总和IIIclassSolution{List<List<Integer>>res=newArrayList<>();List<Integer>paths=newArrayList<>();......
  • 代码随想录第二十四天 | 回溯算法
    今天结束了二叉树的学习,开始新的一章了77.组合classSolution{List<List<Integer>>res=newArrayList<List<Integer>>();List<Integer>list=newArra......
  • 数字n代表生成括号的对数,设计一个函数,用于能够生成所有可能的并且有效的括号组合 回溯
    题目描述:数字n代表生成括号的对数,设计一个函数,用于能够生成所有可能的并且有效的括号组合如  n=2 则输出//['(())','()()']  n=3则输出//['((()))','(()()......
  • 回溯去重
    1.参考代码随想录2.回溯法经典问题组合问题:N个数里面按一定规则找出k个数的集合排列问题:N个数按一定规则全排列,有几种排列方式切割问题:一个字符串按一定规则有几种......
  • 01背包问题回溯
    includedefineMAX10000usingnamespacestd;//inti,j;intn,m;//n标志背包容量,m标致物品个数intresult=-9999;intvis[MAX]={0};intw[MAX]={0};intv[MAX......
  • 回溯-子集
    组合是无序的,满足方案要求即可,对应不同的题意,有时候元素可以重复,有时候不能重复。排列是有序的,同一批元素可以有多种排列。子集跟上面两种又不同,首先空集是子集,一个元素......
  • 回溯-排列
    跟组合类似,排列也是穷举所有可行解,区别在于排列是有序的,同一个组合可以有多种排列。比如对组合来说[1,2,3]和[3,2,1]是同一个,但对于排列而言,就是两个。案例1:给定一个不含......
  • 回溯-组合
    组合问题也是需要进行穷举的,使用回溯算法正合适。案例1:给你一个无重复元素的整数数组 candidates和一个目标整数 target ,找出 candidates 中可以使数字和为目标......
  • 回溯-单词搜索
    在二维数组进行单词搜索也是经典的需要采用回溯算法的问题。案例1:给定一个 mxn二维字符网格 board和一个字符串单词 word。如果 word存在于网格中,返回true;否......
  • 回溯-N皇后
    回溯算法其实就是暴力穷举算法,只不过暴力穷举采用了先拆解子问题,然后将子问题使用递归的方式进行求解,并且在不满足条件的情况下,有向上回溯的过程。许多复杂的,规模较大的问......