大家好我是Liyuyue!
本专栏会将本博主刷题历程记录并总结下来,出成讲解的方式供给大家一起学习!
接下来我会讲我刷的LeetCode好题用到的思路、方法分享给大家一起学习,如果大家在看的过程中还有好的方法,可以评论区或者直接找我继续讨论。
如果大家有需要出讲解的题可以给我评论或者私聊我,我帮大家试试水~!给大家一个满意的讲解~!
感谢大家的支持~!
17. 电话号码的字母组合
class Solution {
public:
vector letterCombinations(string digits) {
}
};
这道题还是有些难度的。
这道题就是要我们对它给的digits里的数组对应九宫格里的字母进行一一对应的输出出来,但是只能输入2-9,因为位置1不是字母而是字符。
通过给定的字符串中依次取出数字,通过数字找到对应的字母,然后依次一一对应,用容器存储起来,到digits(给定的字符串)取到 '\0' 也就是取完了,说明也对应的存储起来了,然后再返回。
首先为了容易对应数字与字母的映射,我们需要创建一个数组对数字对应的字符串进行存储:
string count_str[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
但是还是有要求的,因为如果直接在类里这样写,就相当于类的成员变量,这里的 = 不是赋值,而是给的缺省值:
class Solution {
public:
string count_str[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
vector letterCombinations(string digits) {
}
};
所以不能这么写,可以给成static静态的,但是静态的必须要在类外面初始化,那不如直接给成全局的,直接在外面定义就可以:
string count_str[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
class Solution {
public:
vector letterCombinations(string digits) {
}
};
其实通过上面的总体概括,我们就应该能感觉到这里用递归来写会方便很多,因为是多个字符串一一组合,而递归正可以做这种事情:
当在遍历ad的时候,遍历到z的时候返回到第二层,然后继续遍历第二层,遍历第二层第二个字母的时候再向下进行依次遍历......
既然我们确定了要用递归来解决这个问题,那么我们就要想如何写递归条件,
我们要定义一个变量,用来记录递归了几层(深度),也就是判断digits中的字符串取没取完。然后定义一个vector容器进行对stringd类(字符串)进行存储,还要定义一个string用来对字符串递归的时候进行传递。
这里进行传递的意思是:第一次记录了a,然后将a传递到下一层,记录ad,然后将ad传递到下一层,记录adw,因为这是最后一层,然后继续记录adx、ady、adz,记录完了,返回到第二层。所以这时我们就要注意了,我们用string进行传递的时候,不能传引用,因为我们的目的是让第二层只传递的是第一层是字母,如果第三层的改变影响从第一层传给第二层的字母,那就达不成我们想要的结果了。
递归的条件说完了,继续说说递归结束的条件:因为我们定义了一个记录深度的变量,当深度达到最后一层,也就是到了 数字映射的字符串string的字符个数就结束此递归,但是结束之前要将用来记录的string里的字符串加载到vector
最后要注意的就是如果穿过来的为空,直接返回一个空串就可以了。
这下思路就讲完了,大家可以尝试写一写,其实写起来很简单,但是思路不是很好想到,各种对数据进行存储和传递。
相信经过讲解,大家也对这个思路很清晰了,大家如果还没理解清楚,一定要记住我设置的那些变量,然后画递归图,一步步分析,只有了解了递归的方式和递归的路程,才能真正明白是怎么进行的递归。
我对下面的代码进行了注释。
这里有的人喜欢对str用传引用,如果只是传引用的话是不对的,因为string& str这个形参是通过str + ch 这个实参传递的,这个实参是临时变量,要想使用传引用,必须要const string& str,这样才可以,因为const会延长临时变量的生命周期。
所以我不推荐用,因为其实string str 和 const string& str 在效率上是一样的,编译器会给string str优化,因为传来的是str + ch,会创建一个临时变量进行构造,然后传给形参再拷贝构造,编译器会直接优化为直接拷贝构造,所以是一样的!
string count_str[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
class Solution {
public:
void _letterCombinations(const string& digits,int i, string str, vector& ret)
// void _letterCombinations(const string& digits,int i, const string& str, vector& ret)
{ // 建议使用第一个(没注释掉的)
if(digits.size() == i) // 递归结束条件
{
ret.push_back(str);
return;
}
int num = digits[i] - '0'; // 将字符转换为数字
const string& letters = count_str[num];
for(auto ch : letters)
_letterCombinations(digits, i + 1, str + ch, ret); // 进行递归
}
vector letterCombinations(string digits) {
vector ret; // 用来存储的容器
if(digits.empty()) // 看是不是为空
return ret;
int i = 0;
string s; // 用来递归的字符串
_letterCombinations(digits, i, s, ret);
return ret;
}
};
如上就是 电话号码的字母组合 的解析,接下来本专辑会持续更新【刷爆LeetCode】,和大家一起爆扣LeetCode!!!,如果大家喜欢看此文章并且有收获,可以时刻关注我,本专栏持续更新!
感谢大家观看,感谢大家支持!