(A卷,100分)- 字母组合(Java & JS & Python & C)
题目描述
每个数字关联多个字母,关联关系如下:
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、根据提供的数字字符串,得到字母组合字符串。这块其实就是求组合问题,可以使用回溯算法,逻辑可以参考:LeetCode - 17 电话号码的字母组合_伏城之外的博客-CSDN博客
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] == '\0') { int i = 0; while (filter[i] != '\0') { if (strchr(path, filter[i]) == NULL) { printf("%s,", path); return; } i++; } return; } // 当前层级的数字 int num = nums[level] - '0'; // 该数字关联的多个字母 char *letters = map[num]; // 遍历当前层级可选的字母 int i = 0; while (letters[i] != '\0') { // 选择字母加入当前组合 path[path_size++] = letters[i]; // 继续组合下一个层级的字母选择 dfs(level + 1, path, path_size); path_size--; i++; } } int main() { gets(nums); gets(filter); char path[MAX_SIZE] = {'\0'}; // 回溯算法求组合 dfs(0, path, 0); return 0; }