力扣:17. 电话号码的字母组合

力扣:17. 电话号码的字母组合

描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

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

示例 1:

输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
示例 2:

输入:digits = “”
输出:[]
示例 3:

输入:digits = “2”
输出:[“a”,“b”,“c”]

提示:

0 <= digits.length <= 4
digits[i] 是范围 [‘2’, ‘9’] 的一个数字。

1.递归

排列组合的方式,例如:
题目中的“23”,对应为“abc”,“def”,按下2和3时,能出现的选择,只有“a”,“b”,"c"和“d”,“e”,“f”,然而按下第一个数字2,“a”,“b”,"c"不能互相排列,再次按下数字3,“d”,“e”,“f”可以和前面的“a”,“b”,"c"互相组合,组合的可能就为[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
可按照下面设计代码:
1.创建数组,存储第一个数字对应的字母
2.将第二个数字对应的字母,遍历一遍,一一添加到数组中

#include<iostream>
#include<vector>
using namespace std;
class Solution{
public:
	string m[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
	vector<string> letterCombinations(string digits){
		vector<string> res;
		for(int i = 0; i < digits.size(); i++){
			combine(res,digits[i]);
		}
		return res;
	}
	void combine(vector<string> & res,char ch){
	int n = res.size();
	int digit = static_cast<int>(ch)-48;
	int l = m[digit].size();
	if(n == 0){
		//第一个数字对应的字母添加到数组中
		for(auto j = 0; j < l; ++j){
			string s(1,m[digit][j]);
			res.push_back(s);
		}
		return;
	}
	for(int i = 0; i < n; ++i){
		//将第二个数字对应的字母,遍历,添加到数组中
		for(int j = 0; j < l - 1; ++j){
			res.push_back(res[i] + m[digit][j]);
		}
		res[i] += m[digit][l-1];
	}
	return;
	}	
};


 int main()
 {
 	Solution solution;
	 string digits = "79";
	 vector<string> result = solution.letterCombinations(digits);
	 cout << "ALL possible combinations for digits " << digits << " are " << endl;
	 for(const string & str:result){
	 	cout << str << " ";
	 }
	 cout << endl;
	return 0;
 }

在这里插入图片描述

2.队列

先将第一个数字对应的字符入队,之后每次从队头取出一个元素,与m[]中字符串中的未组合的字符分别组合,然后放入队尾。

#include<iostream>
#include<queue>
#include<vector>
#include<map>
using namespace std;
class Solution {
public:
    vector<string> letterCombinations(string digits) {
        map<char, string> m = { {'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"},
                                {'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"} };
        std::queue<string> q;
        vector<string> res;
        // 先处理第一个数字。是为了使q不为空。
        for (auto i : m[digits[0]]) {
            string s(1, i);
            q.push(s);
        }  
		//处理第二个及以后的数字
        for (auto i = 1; i < digits.size(); ++ i) {
            int len = q.size();
            for (auto j = 0; j < len; ++ j) {
                string s = q.front();		//队首的字符
                for (auto k = 0; k < m[digits[i]].size(); ++ k) {
                    q.push(s + m[digits[i]][k]);  //队首的字符和余下对应号码未组合的字符组合
                }
                q.pop();  //删除队首的字符
            }
        }
        while (!q.empty()) {
            res.push_back(q.front());
            q.pop();
        }
    return res;
    }
};


int main()
{
	Solution solution;
	string digits = "679";
	vector<string> result = solution.letterCombinations(digits);
	cout << "All possibile combinations for digits " << digits << " are " << endl;
	for(const string & str:result){
		cout << str << " ";
	}
	cout << endl;
	return 0;
}

在这里插入图片描述

3.搜索(深度优先)

3.1

对一个数字对应的字符都搜索(排列)完成后,在进行第二个数字对应的字符搜索(排列),在进行第三个

在这里插入图片描述

和队列的思想类似

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class Solution{
public:
	vector<string> letterCombinations(string digits){
		vector<string>res;
		if(digits.empty()) return res;
		vector<string>letter({"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"});
		string path = "";
		DFS(digits,0,path,res,letter);
		return res;
	}
	void DFS(string digits, int pos, string & path, vector<string> & res, vector<string> & letter){
		if(pos == digits.size()){
			res.push_back(path);
			return;
		}
		for(auto c:letter[digits[pos] - '0']){
			path.push_back(c);
			DFS(digits, pos + 1, path, res, letter);
			path.pop_back();
		}
	}
};


int main()
{
	Solution solution;
	string digits = "679";
	vector<string> result = solution.letterCombinations(digits);
	cout << "All possibile combinations for digits " << digits << " are " << endl;
	for(const string & str:result){
		cout << str << " ";
	}
	cout << endl;
	return 0;
}

在这里插入图片描述

3.2

每次递归调用时,将新的字符直接添加到 path 的末尾,而不是像之前那样在函数调用之间不断地对 path 进行 push_back 和 pop_back 操作。这种直接在递归调用中更新 path 的方式避免了频繁的操作,简化了代码逻辑。

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<string>res;
        if(digits.empty()) return res;
        vector<string>letter({"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"});
        string path = "";
        DFS(digits, 0, path, res, letter);
        return res;
    }
        //此处修改string path,为传值方式
    void DFS(string digits, int pos, string path, vector<string>& res, vector<string>& letter){
        if(pos == digits.size()){
            res.push_back(path);
            return;
        }
        for(auto c: letter[digits[pos] - '0']){
            DFS(digits, pos + 1, path + c, res, letter);
        }
    }
};


int main()
{
	Solution solution;
	string digits = "679";
	vector<string> result = solution.letterCombinations(digits);
	cout << "All possibile combinations for digits " << digits << " are " << endl;
	for(const string & str:result){
		cout << str << " ";
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
力扣官方给的解题方法为第三种:

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<string> combinations;
        if (digits.empty()) {
            return combinations;
        }
        unordered_map<char, string> phoneMap{
            {'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, const 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.at(digit);
            for (const char& letter: letters) {
                combination.push_back(letter);
                backtrack(combinations, phoneMap, digits, index + 1, combination);
                combination.pop_back();
            }
        }
    }
};

力扣:17. 电话号码的字母组合

相关推荐

  1. 100】17.电话号码字母组合

    2024-03-10 21:24:01       58 阅读
  2. 17. 电话号码字母组合

    2024-03-10 21:24:01       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-10 21:24:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-10 21:24:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-10 21:24:01       82 阅读
  4. Python语言-面向对象

    2024-03-10 21:24:01       91 阅读

热门阅读

  1. HarmonyOS4.0入门学习需要学习哪些知识点呢?

    2024-03-10 21:24:01       44 阅读
  2. openssl3.2 - exp - export RSA pubKey from RSA privKey on memory

    2024-03-10 21:24:01       38 阅读
  3. 8. Go实现Gin服务优雅关机与重启

    2024-03-10 21:24:01       42 阅读
  4. Android 二维码相关(一)

    2024-03-10 21:24:01       43 阅读
  5. 计算机基础专升本笔记十二-Excel常用快捷键大全

    2024-03-10 21:24:01       46 阅读
  6. SpringBoot多环境配置和logback日志记录器

    2024-03-10 21:24:01       43 阅读
  7. 关于设置html不让浏览器进行缓存的问题

    2024-03-10 21:24:01       42 阅读
  8. SQL如何添加数据?|SQL添加数据示例

    2024-03-10 21:24:01       47 阅读
  9. 使用Numpy手工模拟梯度下降算法

    2024-03-10 21:24:01       35 阅读
  10. 代码随想录算法训练营day32

    2024-03-10 21:24:01       43 阅读
  11. 软考高级:UML 4+1 视图概念和例题

    2024-03-10 21:24:01       40 阅读
  12. UML统一建模语言在软件开发中作用

    2024-03-10 21:24:01       48 阅读