首页 > 编程语言 >代码随想录算法训练营第二十五天| 216.组合总和III 17.电话号码的字母组合

代码随想录算法训练营第二十五天| 216.组合总和III 17.电话号码的字母组合

时间:2023-09-03 11:33:19浏览次数:37  
标签:216 digits return string index int 随想录 result 字母组合

 

216.组合总和III 

     卡哥建议:如果把 组合问题理解了,本题就容易一些了。 

    题目链接/文章讲解:https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html

    视频讲解:https://www.bilibili.com/video/BV1wg411873x

    做题思路:

   本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度。

   例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。

   选取过程如图:

216.组合总和III

    图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。

   回溯三部曲看卡哥文章吧。

   剪枝优化:

   1,已选元素总和如果已经大于n(图中数值为4)了,那么往后遍历就没有意义了,直接剪掉。

   2,for循环的范围也可以剪枝,i <= 9 - (k - path.size()) + 1就可以了,和昨天的题一样

    本题代码:

 1 class Solution {
 2 private:
 3     vector<vector<int>> result; // 存放结果集
 4     vector<int> path; // 符合条件的结果
 5     void backtracking(int targetSum, int k, int sum, int startIndex) {
 6         if (sum > targetSum) { // 剪枝操作
 7             return; // 如果path.size() == k 但sum != targetSum 直接返回
 8         }
 9         if (path.size() == k) {
10             if (sum == targetSum) result.push_back(path);
11             return;
12         }
13         for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝
14             sum += i; // 处理
15             path.push_back(i); // 处理
16             backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
17             sum -= i; // 回溯
18             path.pop_back(); // 回溯
19         }
20     }
21 
22 public:
23     vector<vector<int>> combinationSum3(int k, int n) {
24         result.clear(); // 可以不加
25         path.clear();   // 可以不加
26         backtracking(n, k, 0, 1);
27         return result;
28     }
29 };

 

 17.电话号码的字母组合 

     卡哥建议:本题大家刚开始做会有点难度,先自己思考20min,没思路就直接看题解。 

    题目链接/文章讲解:https://programmercarl.com/0017.%E7%94%B5%E8%AF%9D%E5%8F%B7%E7%A0%81%E7%9A%84%E5%AD%97%E6%AF%8D%E7%BB%84%E5%90%88.html

    视频讲解:https://www.bilibili.com/video/BV1yV4y1V7Ug

    做题思路:

     电话按键上2~9数字上对应着3个或4个字母,题目求的是输入数字,输出字母的组合,可以使用map或者定义一个二维数组,例如:string letterMap[10][],来做映射,10行,4列的二维数组,代码见卡哥文章。

 

     图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。

   需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组result保存起来,       代码中的 index 是从0开始的,是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串“23”),就是下标,同时index也表示树的深度。 

   本题代码:

 1 class Solution {
 2 private:
 3     const string letterMap[10] = { //二维数组,10行,列并没有定义,但能看出来
 4         "", // 0
 5         "", // 1
 6         "abc", // 2
 7         "def", // 3
 8         "ghi", // 4
 9         "jkl", // 5
10         "mno", // 6
11         "pqrs", // 7
12         "tuv", // 8
13         "wxyz", // 9
14     };
15 public:
16     vector<string> result;//放叶子节点的结果
17     string s;
18     void backtracking(const string& digits, int index) {
19         if (index == digits.size()) {
20             result.push_back(s);
21             return;
22         }
23         int digit = digits[index] - '0';        // 将index指向的数字转为int,比如digits[0]="2",减完后,就是2了
24         string letters = letterMap[digit];      // 取数字对应的字符集,比如,letterMap[2]="abc",然后在二维数组里就能找到对应的字符串
25         for (int i = 0; i < letters.size(); i++) { //树的结构,看上图
26             s.push_back(letters[i]);            // 处理
27             backtracking(digits, index + 1);    // 递归,注意index+1,一下层要处理下一个数字了
28             s.pop_back();                       // 回溯
29         }
30     }
31     vector<string> letterCombinations(string digits) {
32         s.clear();
33         result.clear();
34         if (digits.size() == 0) {
35             return result;
36         }
37         backtracking(digits, 0);
38         return result;
39     }
40 };

 

 

 

标签:216,digits,return,string,index,int,随想录,result,字母组合
From: https://www.cnblogs.com/romantichuaner/p/17646828.html

相关文章

  • [代码随想录]Day34-动态规划part02
    题目:62.不同路径思路:首先想到的是数论方法组合数其实就是向右和向下的步数是固定的,就找一个组合的个数就可以了。状态转移方程:一个位置的路径数就是,上面位置和左面位置路径数的和按照动规五部曲来分析:确定dp数组(dptable)以及下标的含义:dp[i][j]:表示从(0,0)出发,到(i,j)有d......
  • 代码随想录——数组篇
    二分查找题目链接注意:求均值防溢出,left+(right-left)/2等价于(left+right)/2。原地移除元素题目链接给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用O(1)额外空间并原地修改输入......
  • [代码随想录]Day33-动态规划part01
    题目:509.斐波那契数思路:动规五部曲:这里我们要用一个一维dp数组来保存递归的结果确定dp数组以及下标的含义dp[i]的定义为:第i个数的斐波那契数值是dp[i]确定递推公式为什么这是一道非常简单的入门题目呢?因为题目已经把递推公式直接给我们了:状态转移方程dp[i]=dp[i-......
  • [6]-代码随想录算法训练营-dat7-哈希表-part2
    代码随想录算法训练营第七天|哈希表-part21.LeetCode454.四数相加II题目https://leetcode.cn/problems/4sum-ii/submissions/思路无刷随想录后想法将四数相加转化为两数之和借用unordered_map,利用两数之和思想解决本问题实现困难代码尚模糊,不过整个......
  • unistr函数将数据库表中的unicode转为字符(\u2161转为罗马数字Ⅱ)
    一、背景在前端页面用户输入罗马数字Ⅱ时,数据存到数据库会转为Unicode编码\u2161,需通过函数重新将Unicode编码转换回去。二、uninstr函数unistr(\xxxx)将Unicode编码转换回原来的形式,因为Unicode是带有u的,即\uxxxx,需要将u给去掉,变成oracle可识别的格式,否则oracle会提示错误。......
  • [代码随想录]Day30-贪心算法part04
    题目:860.柠檬水找零思路:收到钱三种情况:5刀:直接收起来就可以了,不需要找钱10刀:收到10刀,需要找5刀,如果没有5刀,就返回false,否则5刀-120刀:收到20刀(但是没用,找钱也不能找20所以不需要记录数量),优先考虑找105,因为10只能在这里用,其次再考虑找555代码:funclemonadeChange(bil......
  • 代码随想录第6天|242.有效的字母异位词;349.两个数组的交集;202.快乐数;1.两数之和;
     unordered_map<int,int>map;  unordered_set<int>result;vector<vector<int>>res(n,vector<int>(n,0));声明了长度为n*n的二维数组在C++中,auto是一个关键字,用于实现类型推导,使编译器能够根据变量的初始化表达式来自动推断其数据类型。它在C++11标准中引入,......
  • [代码随想录]Day29-贪心算法part03
    题目:1005.K次取反后最大化的数组和思路:思路是:先把负数从小到大变成正数(即绝对值由大到小)如果还需要变化(k>0),就变化最小的数在第一步变化的同时顺便记录一个数组和,那么结束之后会有三种情况:k==0;也就是说负数的个数大于等于k,直接返回结果k%2==0;此时全是正整数,......
  • 代码随想录第4天|链表复习
    做这种算法题真的要放平心态,你想不到思路的时候不要觉得自己太笨,其实想不到很正常,今天环形链表和相交链表这两道题,真的一点思路都没有,环形链表是最难理解的,在课堂上学的链表上的那点东西拿来做这种题确实还是差很多,我真的非常感谢这个做题的训练营,没有它我自己真的做不下去,现在跟......
  • 代码随想录算法训练营第二十四天| 理论基础 77. 组合
     理论基础    卡哥建议:其实在讲解二叉树的时候,就给大家介绍过回溯,这次正式开启回溯算法,大家可以先看视频,对回溯算法有一个整体的了解。   题目链接/文章讲解:https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8......