栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

上好的刷题Day19

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

上好的刷题Day19

详解 【回溯算法】本质穷举

【题目1】 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。
class Solution {
    List> result = new ArrayList<>();
    LinkedList path = new LinkedList<>();
    public List> combine(int n, int k) {
        combineHelper(n, k, 1);
        return result;
    }

    
    private void combineHelper(int n, int k, int startIndex){
        //终止条件
        if (path.size() == k){
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = startIndex; i <= n - (k - path.size()) + 1; i++){
            path.add(i);
            combineHelper(n, k, i + 1);
            path.removeLast();
        }
    }
}

【题目2】 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9
每个数字 最多使用一次 
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
class Solution {
    List> result = new ArrayList<>();
    LinkedList path = new LinkedList<>();
    public List> combinationSum3(int k, int n) {
        backTracing(k,n,0,1);
        return result;
    }
    
    public void backTracing(int k,int n,int sum, int startIndex){
        if(sum > n)
            return;
        if(path.size() == k  ){
            if(n == sum)
                result.add(new ArrayList<>(path));
            return;
        }
        for(int i = startIndex;i<= 10 - (k-path.size());i++){
            sum+=i;
            path.add(i);
            backTracing(k,n,sum,i+1);
            sum-=i;
            path.removeLast();
        }
    }
}
【题目3】不同集合取组合 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

class Solution {
    List list = new LinkedList<>();
    StringBuilder temp = new StringBuilder();
    public List letterCombinations(String digits) {
        if(digits == null || digits.length() == 0)
            return list;
        String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        backTracing(digits,numString,0);
        return list;
    }
    public void backTracing(String digits,String[] numString,int num){
        if(num == digits.length()){
            list.add(temp.toString());
            return;
        }
        String str = numString[digits.charAt(num)-'0'];
        for(int i = 0;i 
【题目4】 
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。  
对于给定的输入,保证和为 target 的不同组合数少于 150 个。 
本题还需要startIndex来控制for循环的起始位置,对于组合问题,什么时候需要startIndex呢? 
我举过例子,如果是一个集合来求组合的话,就需要startIndex, 
如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex, 
注意以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路,后面我再讲解排列的时候就重点介绍。 
class Solution {
    List> result = new ArrayList<>();
    LinkedList path = new LinkedList<>();
    public List> combinationSum(int[] candidates, int target) {
        backTracing(candidates,target,0,0);
        return result;
    }
    public void backTracing(int[] candidates,int target,int sum,int startIndex){
        if(sum > target)
            return;
        if(sum == target){
            result.add(new ArrayList<>(path));
            return;
        }
        for(int i = startIndex;i 
//===============================剪枝优化=================
        for(int i = startIndex;i target)
                break;
            path.add(candidates[i]);
            backTracing(candidates,target,sum+candidates[i],i);
            path.removeLast();
        }

//但是要注意,必须排序,要不然不能全部遍历到所有组合,会直接break掉。

//但是要注意,必须排序,要不然不能全部遍历到所有组合,会直接break掉。

//但是要注意,必须排序,要不然不能全部遍历到所有组合,会直接break掉。
【题目5】 设计去重操作  遍历之前Arrays.sort(candidates); 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。  去重细节
class Solution {
    List> lists = new ArrayList<>();
    Deque deque = new LinkedList<>();
    int sum = 0;

    public List> combinationSum2(int[] candidates, int target) {
        //为了将重复的数字都放到一起,所以先进行排序
        Arrays.sort(candidates);
        //加标志数组,用来辅助判断同层节点是否已经遍历
        boolean[] flag = new boolean[candidates.length];
        backTracking(candidates, target, 0, flag);
        return lists;
    }

    public void backTracking(int[] arr, int target, int index, boolean[] flag) {
        if (sum == target) {
            lists.add(new ArrayList(deque));
            return;
        }
        for (int i = index; i < arr.length && arr[i] + sum <= target; i++) {
            //出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
            if (i > 0 && arr[i] == arr[i - 1] && !flag[i - 1]) {
                continue;
            }
            flag[i] = true;
            sum += arr[i];
            deque.push(arr[i]);
            //每个节点仅能选择一次,所以从下一位开始
            backTracking(arr, target, i + 1, flag);
            int temp = deque.pop();
            flag[i] = false;
            sum -= temp;
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821748.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号