题目描述
每个数字关联多个字母,关联关系如下:
- 0 关联 “a”,”b”,”c”
- 1 关联 “d”,”e”,”f”
- 2 关联 “g”,”h”,”i”
- 3 关联 “j”,”k”,”l”
- 4 关联 “m”,”n”,”o”
- 5 关联 “p”,”q”,”r”
- 6 关联 “s”,”t”
- 7 关联 “u”,”v”
- 8 关联 “w”,”x”
- 9 关联 “y”,”z”
输入一串数字后,通过数字和字母的对应关系可以得到多个字母字符串(要求按照数字的顺序组合字母字符串);
屏蔽字符串:屏蔽字符串中的所有字母不能同时在输出的字符串出现,如屏蔽字符串是abc,则要求字符串中不能同时出现a,b,c,但是允许同时出现a,b或a,c或b,c等;
给定一个数字字符串和一个屏蔽字符串,输出所有可能的字符组合;
例如输入数字字符串78和屏蔽字符串ux,输出结果为uw,vw,vx;数字字符串78,可以得到如下字符串uw,ux,vw,vx;由于ux是屏蔽字符串,因此排除ux,最终的输出是uw,vw,vx;
输入描述
第一行输入为一串数字字符串,数字字符串中的数字不允许重复,数字字符串的长度大于0,小于等于5;
第二行输入是屏蔽字符串,屏蔽字符串的长度一定小于数字字符串的长度,屏蔽字符串中字符不会重复;
输出描述
输出可能的字符串组合
注:字符串之间使用逗号隔开,最后一个字符串后携带逗号
用例
输入 | 78 ux |
输出 | uw,vw,vx, |
说明 | 无 |
输入 |
78 |
输出 | uw,vw, |
说明 | 无 |
题目解析
本题由两块逻辑组成:
1、根据提供的数字字符串,得到字母组合字符串。这块其实就是求组合问题,可以使用回溯算法,逻辑可以参考:
2、排除包含屏蔽字符串的字母组合字符串,而本题中判断一个字符串是否包含另一个字符串的逻辑是:屏蔽字符串中的所有字母不能同时在输出的字符串中出现
数字字符串中的数字不允许重复
屏蔽字符串中字符不会重复
JS算法源码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
const nums = await readline();
const filter = await readline();
const map = [
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqr",
"st",
"uv",
"wx",
"yz",
];
const result = [];
/**
* 回溯算法求组合
* @param {*} level 组合的层级
* @param {*} path 记录组合字符串
*/
function dfs(level, path) {
// 组合层数到达要求时,当前组合字符串完成
if (level == nums.length) {
const set = new Set(path);
for (let c of filter) {
if (!set.has(c)) {
result.push(path.join(""));
return;
}
}
return;
}
// 当前层级的数字
const num = nums[level] - "0";
// 该数字关联的多个字母
const letters = map[num];
// 遍历当前层级可选的字母
for (let i = 0; i < letters.length; i++) {
// 选择字母加入当前组合
const letter = letters[i];
path.push(letter);
// 继续组合下一个层级的字母选择
dfs(level + 1, path);
path.pop();
}
}
// 回溯算法求组合
dfs(0, [], result);
// 拼接结果字符串
console.log(result.join(",") + ",");
})();
Java算法源码
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
static String nums;
static String filter;
static String[] map = {"abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx", "yz"};
static ArrayList<String> result = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
nums = sc.nextLine();
filter = sc.nextLine();
System.out.println(getResult());
}
public static String getResult() {
// 回溯算法求组合
dfs(0, new LinkedList<>());
// 拼接结果字符串
StringBuilder sb = new StringBuilder();
result.forEach(s -> sb.append(s).append(","));
return sb.toString();
}
/**
* 回溯算法求组合
*
* @param level 组合的层级
* @param path 记录组合字符串
*/
public static void dfs(int level, LinkedList<Character> path) {
// 组合层数到达要求时,当前组合字符串完成
if (level == nums.length()) {
HashSet<Character> set = new HashSet<>(path);
for (int i = 0; i < filter.length(); i++) {
if (!set.contains(filter.charAt(i))) {
StringBuilder sb = new StringBuilder();
path.forEach(sb::append);
result.add(sb.toString());
return;
}
}
return;
}
// 当前层级的数字
int num = nums.charAt(level) - '0';
// 该数字关联的多个字母
String letters = map[num];
// 遍历当前层级可选的字母
for (int i = 0; i < letters.length(); i++) {
// 选择字母加入当前组合
char letter = letters.charAt(i);
path.addLast(letter);
// 继续组合下一个层级的字母选择
dfs(level + 1, path);
path.removeLast();
}
}
}
Python算法源码
# 输入获取
numsStr = input()
filterStr = input()
dic = ["abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx", "yz"]
result = []
# 算法入口
def getResult():
# 回溯算法求组合
dfs(0, [])
# 拼接结果字符串
return ",".join(result) + ","
def dfs(level, path):
"""
回溯算法求组合
:param level: 组合的层级
:param path: 记录组合字符串
"""
if level == len(numsStr): # 组合层数到达要求时,当前组合字符串完成
pathSet = set(path)
for c in filterStr:
if c not in pathSet:
result.append("".join(path))
return
return
# 当前层级的数字
num = ord(numsStr[level]) - ord('0')
# 该数字关联的多个字母
letters = dic[num]
# 遍历当前层级可选的字母
for letter in letters:
# 选择字母加入当前组合
path.append(letter)
# 继续组合下一个层级的字母选择
dfs(level + 1, path)
path.pop()
# 算法调用
print(getResult())
C算法源码
#include <stdio.h>
#include <string.h>
#define MAX_SIZE 6
char nums[MAX_SIZE];
char filter[MAX_SIZE];
char *map[] = {"abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx", "yz"};
void dfs(int level, char path[], int path_size) {
// 组合层数到达要求时,当前组合字符串完成
if (nums[level] == '