37 数字组合II(Combination Sum II)

news/2024/7/20 20:15:42 标签: 算法, 深度优先

文章目录

    • 1 题目
    • 2 解决方案
      • 2.1 思路
      • 2.2 图解
      • 2.3 时间复杂度
      • 2.4 空间复杂度
    • 3 源码

1 题目

题目:数字组合II(Combination Sum II)
描述:给定一个数组 num 和一个整数 target。 找到 num 中所有的数字之和为 target 的组合。

  1. 在同一个组合中, num 中的每一个数字仅能被使用一次。
  2. 所有数值 (包括 target ) 都是正整数。
  3. 返回的每一个组合内的数字必须是非降序的。
  4. 返回的所有组合之间可以是任意顺序。
  5. 解集不能包含重复的组合。

lintcode题号——153,难度——medium

样例1:

输入: num = [7,1,2,5,1,6,10], target = 8
输出: [[1,1,6],[1,2,5],[1,7],[2,6]]

样例2:

输入: num = [1,1,1], target = 2
输出: [[1,1]]
解释: 解集不能包含重复的组合

2 解决方案

2.1 思路

  与数字组合的第一题1相比,多了一个条件,每个数字只能使用一次。该题无法提前在原序列中去重,需要在递归过程中完成去重,目标是在同一层级去除重复的分支。

2.2 图解

num = [1,1,2,2,3], target = 5的情况下,深度优先搜索的图如下:

null
1
1
抛掉重复
2
2
抛掉重复
3
1
2
2
抛掉重复
3
2
2
抛掉重复
3
2
已超过5
1+1+3=5
2
1+2+2=5
3
已超过5
不足5
2
3
已超过5
3
2+3=5

2.3 时间复杂度

  深度优先搜索的时间复杂度是逻辑图上的节点数(即所有元素的组合数,n个元素,每个元素都有取或不取两种可能,所以是2的n次方)与处理每个节点的耗时(for循环n次)的乘积,该题的算法的时间复杂度为O(2^n * n)。

深度优先搜索的时间复杂度计算没有通用的方式,只能根据具体题目计算,可以理解成看作答案个数与构造每个答案花费的时间的乘积。

2.4 空间复杂度

  使用了vector数据结构保存节点,算法的空间复杂度为O(n)。

3 源码

细节:

  1. 与前一题不同的是,dfs中的序号i每次加一,取下一个数。
  2. 去重的方式需要使用同一层级的去重方式,即i != startindex,而不能简单使用i != 0
  3. 去重的方式也可以使用set,使用set去重不要求原序列有序,更加通用,同一层级去重不需要回溯。
  • i与startIndex比较,它判断每层的非首元素和原序列前一个元素是否相同,首先是防止i-1越界,它能够防止同一层级中出现相同的元素,但不会禁止各个分支的第一个分叉(即i=startIndex)中出现与原序列前一个元素重复的元素。即示例中的竖分支中可以存在相同元素,而同一层级的相同元素则会被去重。

C++版本:

/**
* @param num: Given the candidate numbers
* @param target: Given the target number
* @return: All the combinations that sum to target
*/
vector<vector<int>> combinationSum2(vector<int> &num, int target) {
    // write your code here
    vector<vector<int>> results;
    if (num.empty())
    {
        return results;
    }

    sort(num.begin(), num.end());
    
    vector<int> path;
    dfs(num, path, 0, target, results);
    return results;
}

void dfs(vector<int> & num, vector<int> path, int startIndex, int remainTarget, vector<vector<int>> & results)
{
    if (remainTarget == 0)
    {
        results.push_back(path);
        return;
    }

    //set<int> duplicate;
    for (int i = startIndex; i < num.size(); i++)
    {
        // 用于在同一个层级之间去重,不考虑每层的第一个元素即i=startIndex
        if (i != startIndex && num.at(i) == num.at(i - 1))
        {
            continue;
        }

        //if (duplicate.find(num.at(i)) != duplicate.end())
        //{
        //    continue;
        //}

        // 结果超过目标值,则停止,防止后续的无效搜索
        if (remainTarget < num.at(i))
        {
            break;
        }

        path.push_back(num.at(i));
        // 题中不能重复取同一个值,所以递归依然从i + 1开始,而不是i
        dfs(num, path, i + 1, remainTarget - num.at(i), results);
        path.pop_back();
    }
}

  1. 数字组合:https://blog.csdn.net/SeeDoubleU/article/details/124418403 ↩︎


http://www.niftyadmin.cn/n/1544686.html

相关文章

38 分割回文串(Palindrome Partitioning)

文章目录1 题目2 解决方案2.1 思路2.2 时间复杂度2.3 空间复杂度3 源码1 题目 题目&#xff1a;分割回文串&#xff08;Palindrome Partitioning&#xff09; 描述&#xff1a;给定字符串 s&#xff0c;需要将它分割成一些子串&#xff0c;使得每个子串都是回文串。返回所有可…

WPF之属性

属性程序的本质就是“数据算法”&#xff0c;在程序中&#xff0c;数据表现为各种各样的变量&#xff0c;算法表现为各种各样的函数。 在面向对象的时代&#xff0c;类把散落在程序中的变量和函数进行归档并控制对它们的访问。被封装在类里的变量称为字段&#xff08;Field&…

39 全排列(Permutations)

文章目录1 题目2 解决方案2.1 思路2.2 图解2.3 时间复杂度2.4 空间复杂度3 源码4 另解4.1 交换法4.2 插空法1 题目 题目&#xff1a;全排列&#xff08;Permutations&#xff09; 描述&#xff1a;给定一个数字列表&#xff0c;返回其所有可能的排列。假设没有重复的数字。 li…

40 全排列II(Permutations II)

文章目录1 题目2 解决方案2.1 思路2.2 图解2.3 时间复杂度2.4 空间复杂度3 源码4 另解4.1 交换法1 题目 题目&#xff1a;全排列II&#xff08;Permutations II&#xff09; 描述&#xff1a;给出一个具有重复数字的列表&#xff0c;找出列表所有不同的排列。 lintcode题号——…

互联网+

作者&#xff1a;卢彦 来源&#xff1a;《互联网思维2.0&#xff1a;传统企业互联网转型》 “当今企业之间的竞争&#xff0c;不是产品之间的竞争&#xff0c;而是商业模式之间的竞争” ——现代管理学之父 彼得德鲁克 “互联网”企业四大落地系统&#xff08;商业模式、管理模…

struts2 基本用法

Struts2必需库&#xff1a; commons-fileupload.jar、commons-io-1.3.2.jar、freemarker-2.3.16.jar、javassist-3.7.ga.jar、ognl-3.0.jar、 struts-core-2.2.1.jar和xwork-core-2.2.1.jar struts.xml <?xml version"1.0" encoding"UTF-8"?><…

41 N皇后(N-Queens)

文章目录1 题目2 解决方案2.1 思路2.2 图解2.3 时间复杂度2.4 空间复杂度3 源码1 题目 题目&#xff1a;N皇后&#xff08;N-Queens&#xff09; 描述&#xff1a;N皇后问题是将n个皇后放置在n*n的棋盘上&#xff0c;皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行&…

Centos 安装 python2.7.10以及pip

安装python2.7.10 1. 下载安装包并解压 wget https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz tar -xf Python-2.7.10.tgz 2. 进行编译和安装 ./configure --prefix/usr/local/bin make && make install 3. 调整/usr/bin/python的连接 因为原先有安装pyth…