每日一题~组合总数III

原题链接: 216. 组合总和 III - 力扣(LeetCode)

题目描述:

思路分析:

这是一个组合的问题,所以我们可以使用深度优先搜索(DFS)的方式将所有的情况都列举出来,然后将其中符合条件的情况添加到列表中,最后返回这个列表就可以了。详细步骤如下:

1、准备一个 tmp 列表保存当前集合的数据,用 list 列表保存所有符合条件的列表,用 sum 来记录当前 tmp 列表中的数据之和,用一个 used 数组来记录该数据是否已经被使用

2、使用 DFS 来找到所有组合,当 tmp 的 size = k 时,说明 tmp 已经满了,如果 sum = n,说明这个 tmp 符合条件,但是需要注意的是【1,2,3】和【1,3,2】是属于同一个集合,所以我们还需要进行去重操作,因为我们是从小到大来搜索的,所以【1,2,3】一定在【1,3,2】的前面,去重的时候我们只需要判断 tmp.get(i+1) 是否小于 tmp.get(i) 就可以了,如果 tmp.get(i+1) < tmp.get(i),则说明 list 中已经保存了该情况,直接返回即可

代码示例:

java 复制代码
class Solution {
    // 标记是否使用
    int[] used = new int[10];
    // 记录链表中的数据和
    int sum = 0;
    List<List<Integer>> list = new ArrayList<>();
    LinkedList<Integer> tmp = new LinkedList<>();
    public List<List<Integer>> combinationSum3(int k, int n) {
        // 递归
        dfs(1,k,n);
        return list;
    }
    public void dfs(int x,int k, int n) {
        if(tmp.size() == k) {
            if(sum == n) {
                // 去重操作
                for(int i = 0; i < k-1; i++) {
                    if(i+1 < k && tmp.get(i) > tmp.get(i+1)) {
                        return;
                    }
                }
                list.add(new ArrayList<>(tmp));
            }
            return;
        }
        for(int i = x; i < 10; i++) {
            if(used[i] == 0) {
                tmp.add(i);
                sum += i;
                used[i] = 1;
                dfs(x+1,k,n);
                tmp.removeLast();
                sum -= i;
                used[i] = 0;
            
            }
            
        }
    }
}

可以看出,上述步骤还是比较麻烦的,我们不仅需要找出来 1~9 所有的组合情况,还需要对这些情况进行一下去重操作,这样一来效率就非常低了。如果我们在寻找组合的时候,就进行剪枝,只保存升序的列表例如,【1,2,3】,【1,2,4】,【1,2,5】,......【7,8,9】,这样的话我们就不需要找到所有的组合情况,而且还节省了去重的步骤,相比第一种暴力的解决方法就显得高效了很多。

java 复制代码
class Solution {
    // 标记是否使用
    int[] used = new int[10];
    // 记录链表中的数据和
    int sum = 0;
    List<List<Integer>> list = new ArrayList<>();
    LinkedList<Integer> tmp = new LinkedList<>();
    public List<List<Integer>> combinationSum3(int k, int n) {
        // 递归
        dfs(1,k,n);
        return list;
    }
    public void dfs(int x,int k, int n) {
        if(tmp.size() == k) {
            if(sum == n) list.add(new ArrayList<>(tmp));            
            return;
        }
        for(int i = x; i < 10; i++) {
            if(used[i] == 0) {
                // 剪枝
                if(tmp.size() > 0 && i < tmp.peekLast()) continue;
                tmp.add(i);
                sum += i;
                used[i] = 1;
                dfs(x+1,k,n);
                tmp.removeLast();
                sum -= i;
                used[i] = 0;
            
            }
            
        }
    }
}
相关推荐
Fuly102413 分钟前
大模型剪枝(Pruning)技术简介
算法·机器学习·剪枝
Xの哲學19 分钟前
Linux网卡注册流程深度解析: 从硬件探测到网络栈
linux·服务器·网络·算法·边缘计算
bubiyoushang88822 分钟前
二维地质模型的表面重力值和重力异常计算
算法
仙俊红1 小时前
LeetCode322零钱兑换
算法
颖风船1 小时前
锂电池SOC估计的一种算法(改进无迹卡尔曼滤波)
python·算法·信号处理
551只玄猫1 小时前
KNN算法基础 机器学习基础1 python人工智能
人工智能·python·算法·机器学习·机器学习算法·knn·knn算法
charliejohn1 小时前
计算机考研 408 数据结构 哈夫曼
数据结构·考研·算法
POLITE31 小时前
Leetcode 41.缺失的第一个正数 JavaScript (Day 7)
javascript·算法·leetcode
CodeAmaz1 小时前
一致性哈希与Redis哈希槽详解
redis·算法·哈希算法