题目如下,输入一串数字,根据电话键盘布局输出此数字可能代表的字母组合。
Given a digit string, return all possible letter combinations that the number could represent.
Input:Digit string "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
第一次做这道题目的时候,比较笨,由于2这个key对应了 a, b, c这三个value,所以我尝试着使用了multimap,这个关联容器在key-value为一对多关系的时候使用。对于multi_map的使用比较新鲜,平时几乎不用。这道题目主要参考了C++ Primer中第10章对于multi_set的讲解。
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
using namespace std;
class Solution {
public:
vector<string> letterCombinations(string digits) {
int len_src=(int)digits.length();
vector<string> res;
if(len_src==0){
res.push_back("");
return res;
}
multimap<string,string> digi_str_multi_map;
const string str_arr[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
const string int_arr[10]={"0","1","2","3","4","5","6","7","8","9"};
for(int i=0;i<10;i++){
for(int j=0;j<str_arr[i].length();j++){
string c_tmp=str_arr[i].substr(j,1);
digi_str_multi_map.insert(pair<string, string>(int_arr[i],c_tmp));
}
}
typedef multimap<string,string>::iterator mm_it_type;
set<string> res_set;
set<string>::iterator res_set_it; //1324
for(int i=0;i<len_src;i++){
set<string> tmp_res_set;
if(res_set.empty()) {
string search_item(digits.substr(i,1));
pair<mm_it_type,mm_it_type> pos=digi_str_multi_map.equal_range(search_item);
while(pos.first!=pos.second) {
res_set.insert(pos.first->second);
// std::cout<<"1-1: "<<pos.first->second<<", search_item="<<search_item<<std::endl;
++pos.first;
}
continue;
}else{
string search_item(digits.substr(i,1));
pair<mm_it_type,mm_it_type> pos=digi_str_multi_map.equal_range(search_item);
while(pos.first!=pos.second) {
for(res_set_it=res_set.begin();res_set_it!=res_set.end();res_set_it++) {
string tmp=*res_set_it+pos.first->second;
// std::cout<<"2-1: "<<tmp<<", search_item="<<search_item<<std::endl;
tmp_res_set.insert(tmp);
}
++pos.first;
}
}
res_set.clear();
res_set=tmp_res_set;
}
for(set<string>::const_iterator it=res_set.begin();it!=res_set.end();it++)
res.push_back(*it);
return res;
}
};
后来,重新改了改代码,用普通的数据结构完成了迭代版,也写了递归版。
update1 使用3层vector的嵌套完成迭代版
//迭代版,使用vector的3层嵌套
vector<string> letterCombinations(string digits) {
vector<string> res;
res.push_back("");
if(digits.length()==0)
return res;
const string str_arr[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
// const int int_arr[10]={0,1,2,3,4,5,6,7,8,9};
vector<vector<string>> mapping_vec;
for(int i=0;i<10;i++){
vector<string> tmp;
for(int j=0;j<str_arr[i].size();j++){
string tmp_str(str_arr[i]);
tmp.push_back(tmp_str.substr(j,1));
}
mapping_vec.push_back(tmp);
}
vector<string> tmp_res;
for(int i=0;i<digits.length();i++){
for(int j=0;j<res.size();j++){
string pre_str=res[j];
for(int k=0;k<mapping_vec[atoi(digits.substr(i,1).c_str())].size();k++){
string cur_str=pre_str+mapping_vec[atoi(digits.substr(i,1).c_str())][k];
tmp_res.push_back(cur_str);
}
}
res.swap(tmp_res);
tmp_res.clear();
}
return res;
}
update2 递归版
//递归版
vector<string> letterCombinations2(string digits) {
vector<string> res;
if(digits.length()==0){
res.push_back("");
return res;
}
const string str_arr[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
// const int int_arr[10]={0,1,2,3,4,5,6,7,8,9};
vector<vector<string>> mapping_vec;
for(int i=0;i<10;i++){
vector<string> tmp;
for(int j=0;j<str_arr[i].size();j++){
string tmp_str(str_arr[i]);
tmp.push_back(tmp_str.substr(j,1));
}
mapping_vec.push_back(tmp);
}
string sub_str=digits.substr(1,digits.length()-1);
vector<string> mid_vec=mapping_vec[atoi(digits.substr(0,1).c_str())];
vector<string> pre_res=letterCombinations2(sub_str);
vector<string> cur_res;
for(int i=0;i<mid_vec.size();i++){
for(int j=0;j<pre_res.size();j++){
string cur_string=mid_vec[i]+pre_res[j];
cur_res.push_back(cur_string);
}
}
return cur_res;
}
update: 2015-01-22 使用DFS + map初始化
//DFS 2ms
class Solution {
private:
std::map<string, string> map1;
public:
Solution () {
map1["2"] = "abc";
map1["3"] = "def";
map1["4"] = "ghi";
map1["5"] = "jkl";
map1["6"] = "mno";
map1["7"] = "pqrs";
map1["8"] = "tuv";
map1["9"] = "wxyz";
}
void letterCombinations(string digits, int k, string current, vector<string>& res) {
if (k == digits.length()) {
res.push_back(current);
} else {
for (int i = 0; i < map1[digits.substr(k, 1)].length(); ++i) {
current += map1[digits.substr(k,1)].substr(i,1);
letterCombinations(digits, k+1, current, res);
current = current.substr(0, current.length() - 1);
}
}
}
vector<string> letterCombinations(string digits) {
vector<string> result;
letterCombinations(digits, 0, "", result);
return result;
}
};
update: 2015-03-08 使用DFS + string array初始化
//2ms
class Solution {
private:
string* int2string; // private类型的变量,数组指针。
public:
Solution(){ // 构造函数是public,里面进行string int2string的初始化。
int2string = new string [10];
int2string[0] = "";
int2string[1] = "";
int2string[2] = "abc";
int2string[3] = "def";
int2string[4] = "ghi";
int2string[5] = "jkl";
int2string[6] = "mno";
int2string[7] = "pqrs";
int2string[8] = "tuv";
int2string[9] = "wxyz";
}
void dfs(string &digits, int start, int end, string& current, vector<string>& final_vector) {
if (start == end) {
final_vector.push_back(current);
} else {
int index = digits[start] - '0';
for (int i = 0; i < int2string[index].length(); ++i) {
current = current + int2string[index].substr(i,1);
dfs(digits, start + 1, end, current, final_vector);
current = current.substr(0, current.length() -1);
}
}
}
vector<string> letterCombinations(string digits) {
vector<string> final_vector;
if (digits == "") return final_vector;
string current = "";
dfs(digits, 0, digits.length(), current, final_vector);
return final_vector;
}
};