华为OD题目:字母组合
知识点回溯
时间限制: s 空间限制: 256MB 限定语言: 不限
题目描述:
每个数字对应多个字母,对应关系如下:
0: a,b,c 1: d,e,f 2: g,h,i 3: jk,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:
第二行输入是屏蔽宁符,屏蔽宁符的长度一定小于数宁宁符串的长度,屏蔽宁符串中宁符不会重复,
输出描述
输出可能的宁符串组合
注:宁符串之间使用逗号隔开,最后一个宁符串后携带逗号
示例1
输入:
78
uX
输出:uw,vw,vx,
示例2
输入:
78
x
输出:
uw.vw.
012
x
adg,adh,adi,aeg,aeh,aei,afg,afh,afi,bdg,bdh,bdi,beg,beh,bei,bfg,bfh,bfi,cdg,cdh,cdi,ceg,ceh,cei,cfg,cfh,cfi
解题思路:
- dfs
- 要理解题意,按照数字顺序组合字母,dfs的时候要注意,比如三个数字,那么
- 比如 012, 那么字母必须是数字对应的字母各一个
- 每个数字对应多个字母,对应关系如下:
- 0: a,b,c 1: d,e,f 2: g,h,i 3: jk,l 4: m,n,o 5: p,q,r 6: s,t 7: u,v 8: w,x 9: y,z
- adg,adh,adi,aeg,aeh,aei,afg,afh,afi,bdg,bdh,bdi,beg,beh,bei,bfg,bfh,bfi,cdg,cdh,cdi,ceg,ceh,cei,cfg,cfh,cfi
public class My {
public static String forbiddenStr;
public static char[][] chars = {
{'a', 'b', 'c'},
{'d', 'e', 'f'},
{'g', 'h', 'i'},
{'j', 'k', 'l'},
{'m', 'n', 'o'},
{'p', 'q', 'r'},
{'s', 't'},
{'u', 'v'},
{'w', 'x'},
{'y', 'z'}
};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String numStr = sc.nextLine();
char[] numArray = numStr.toCharArray();
forbiddenStr = sc.nextLine();
List<String> list = new ArrayList<>();
dfs(list, numArray, "", 0);
//打印字符串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
//注意题目,最后是有逗号的","
sb.append(list.get(i)).append(",");
}
System.out.println(sb);
}
/**
* 从numIndex开始, 拼接numArray[numIndex]数字 对应的字符,按顺序,所以不用回溯
* @param list 存放满足条件的字符串
* @param numArray 数字的数组
* @param temp 已经拼接的字符串
* @param numIndex 数字的下标
*/
public static void dfs(List<String> list, char[] numArray, String temp, int numIndex) {
if (temp.length() == numArray.length) {
//如果不包含禁止的字符串,那么可以保留
if (!temp.contains(forbiddenStr)) {
list.add(temp);
}
return;
}
//注意,这里每次只能去一个,得按照数字顺序来(注意: 千万不能for循环numArr)
int num = numArray[numIndex] - '0';
char[] charArr = chars[num];
for (char curr : charArr) {
dfs(list, numArray, temp + curr, numIndex + 1);
}
}
}