LeetCode--电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

输入:"23"输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

最初拿到这个题的时候我想的是通过循环来解决,如果通过循环的话,会有很多的问题,或者可以通过循环来模拟回溯法也是可以实现的。先说一下我的思想,最初我想的是,在开辟好的空间里直接放入数据,比如题目中给出的示例是23,我在放的时候,先把2中的a放三个,再把2中的b放三个,再把c放三个,但是这样就出现了问题,那到3的时候怎么放,如果和上边一样的话就会出现ad ad ad be be be cf cf cf这种情况,因为这是一个循环来解决的,所以存放的方式不能够区别对待,也就是前一个怎么放后一个还是怎么放,所以就出现了我上边的问题。

 这种问题无非就是两种方式循环解决不掉了,那就用递归

 

class Solution {
public:
	vector<string> letterCombinations(string digits) {
		vector<string> str;
		if (digits.size() == 0)
		{
			return str;
		}
		string s;
		Combinations(digits, s, 0, str);
		return str;
	}
private:
	void Combinations(string& digits, string& s, int index, vector<string>& str)
	{
		if (index == digits.size())
		{
			str.push_back(s);
			return;
		}
		int num = digits[index] - '0';
		string letter[10] = { " ", " ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
		for (int i = 0; i < letter[num].size(); i++)
		{
			s.push_back(letter[num][i]);
			Combinations(digits, s, index + 1, str);
			s.pop_back();
		}
		return;
	}
};

不过自己对回溯法加递归的问题理解的并不是很透彻。不知道什么时候要用这个,这里不如就一点一点分析一下整个程序是怎么走的。我们就拿题目示例给的23来演示一下。

 先说一下函数里的参数,分别是题目给的23字符串,以及我们排列组合之后要插入的字符串s,以及index,index是用来记录我们递归层数的,也就是题目给我们的digits的长度是多少就递归几层,index等于digits的说明不能往下循环了。第四个参数就是我们的要返回的vector,注意一定要传引用的形式。

 Combinations(digits, s, 0, str);

最初的时候传入的参数都是空和0,之后进入函数开始递归。

int num = digits[index] - '0';

string letter[10] = { " ", " ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };

for (int i = 0; i < letter[num].size(); i++)

{

s.push_back(letter[num][i]);

Combinations(digits, s, index + 1, str);

s.pop_back();

}

我们先获取出来当前digits的对应位置的数字是多少,然后通过这个数字去我们letter数组里边的下标来找到他对应的字母组合。

  找到之后开始把这些字母分别插入到s字符串里边。第一次循环的时候我们插入了a,然后这是再去调用我们的Combination函数,这时候和第一次调用的时候有所不同,这时候参数里边s已经不是空的了,而是包含一个a,index+1变成了1,str还是没变。当进去之后,我们再次通过num获取digits下标为1的位置的数字,然后还是找到对应的字母组合,开始遍历,之后我们在字符串s中插入了d,然后又进入了循环,s内容是ad,index变成了2这时候。

if (index == digits.size())

{

    str.push_back(s);

    return;

}

这个判断条件就起了作用,把s插入到了str里边然后退出。这时候继续我们让s调用了pop函数,也就是把d给弄了出去,s里边又只剩下了a,for循环继续进行,这次插入的是e,然后又递归,递归到下一层index==digits.size又把ae插入进去,然后返回,回来之后又把e给去掉了,af一样的道理。

这时候就能看到我们的str里边有的是ad ae af  ,然后return一下,继续我们的s.pop之后,s里边的a也没有了,

这时候就退回到了我们的第一层递归,index是0的状态,然后继续我们的for循环,也就是让letter[2][1]进去了也就是b开始进入字符串s

继续之后,bd be bf也都进来了。然后s又把b给pop了出去。c也是一样的道理,当for循环结束之后,就return了。

这时候所有情况都出现了。

回溯法就是在不断的试探,然后把试探的情况组合起来,符合的留下,不符合条件的去掉,所以如果看到题目说所有可能情况,可以往这方面考虑。不过看起来代码简单,但是真正理解透彻的话, 并不是很容易。还是要多联系,多使用。