leetcode 17. Letter Combinations of a Phone Number

题目

电话号码字母组合
leetcode 17. Letter Combinations of a Phone Number

思路

回溯思想(dfs)

本题中无需剪枝
时间复杂度 O(3n * 4m)
空间复杂度 O(n+m)
运行时间 8 ms
内存消耗 7.9 MB

m 是输入中对应 3个字母的数字个数(包括数字 2、3、4、5、6、8),n是输入中对应 4个字母的数字个数(包括数字 7、9),m+n是输入数字的总个数。
时间复杂度:当输入包含 m个对应 3个字母的数字和 n个对应 4个字母的数字时,不同的字母组合一共有 3n * 4m种,需要遍历每一种字母组合
空间复杂度:主要取决于哈希表以及回溯过程中的递归调用层数,哈希表的大小与输入无关,可以看成常数,递归调用层数最大为 m+n(即输入字符串中数字字符个数)

https://editor.csdn.net/md/?articleId=108247459

队列(bfs)

时间复杂度 O(nm(n+m))
空间复杂度 O(n*m)
运行时间 4 ms
内存消耗 6.8 MB

m 是输入中对应 3个字母的数字个数(包括数字 2、3、4、5、6、8),n是输入中对应 4个字母的数字个数(包括数字 7、9),m+n是输入数字的总个数。
时间复杂度:需要n+m轮处理,每轮处理复杂度最大为4nm,总时间复杂度为O(nm(n+m))
空间复杂度:队列长度最大为n*m

https://editor.csdn.net/md/?articleId=108247459

代码

回溯思想(dfs)

class Solution {
	public:
		vector<string> letterCombinations(string digits) {
			vector<string> combinations; //所有结果容器
			if(digits.empty()){ //易错:如果没有这个判断,输入""错误输出[""],而正确输出是[] 
				return combinations;
			} 
			unordered_map<char, string> phoneMap { //hash字典表 
				{'0', ""},
				{'1', ""},
				{'2', "abc"},
				{'3', "def"},
				{'4', "ghi"},
				{'5', "jkl"},
				{'6', "mno"},
				{'7', "pqrs"},
				{'8', "tuv"},
				{'9', "wxyz"}
			};
			string combination;
			backtrack(combinations, phoneMap, digits, 0, combination); //核心方法-回溯 
			return combinations;
		}
		void backtrack(vector<string> &combinations, unordered_map<char,string> phoneMap, const string& digits,int index, string combination) {
			if(index==digits.length()) { //已经走完一个分支 
				combinations.push_back(combination);
			} else {
				char digit = digits[index];
				const string & letters=phoneMap[digit];
				for(const char & letter: letters) {
					combination.push_back(letter);
					backtrack(combinations,phoneMap,digits,index+1,combination);
					combination.pop_back();
				}
			}
		}
};

易错点

if(digits.empty()){ 
	// 易错:如果没有这个判断,输入""错误输出[""],而正确输出是[] 
	// 因为bracktrack方法中第一步即使输入为空,也会插入一个空的字符串到结果容器中
	return combinations;
} 

队列(bfs)

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<string> combinations;
        if(digits.empty()) {
            return combinations;
        }
        queue<string> q;
        q.push("");
        
        string phoneMap []= {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

        for(int i=0; i<digits.length(); i++) {
            string letters = phoneMap[digits[i]-'0'];
            q.push("-"); //分隔符
            while(!q.empty()) {
                string now = q.front();
                q.pop();
                if(now=="-")break; //遇到分隔符表示本轮处理结束 
                for(const char & letter: letters) {
                    string temp = now+letter;
                    q.push(temp);
                }
            }

        }
        while(!q.empty()) {
            combinations.push_back(q.front());
            q.pop();
        }
        return combinations;
    }
};

易错点

分隔符处理

分割符的处理
每轮开始之前插入,队列处理到分隔符表示本轮处理结束,退出

字符串队列插入空字符串

queue<string> q;
q.push("");
cout<<q.size(); //1
posted @ 2020-08-27 09:20  JamieHou  阅读(256)  评论(0编辑  收藏  举报