使用递归和迭代实现笛卡尔积的一种实现方式
在面试题中碰到一个题目:

一个如上图所示的键盘,当输入一个数字m,应输出其对应的字母的所有组合;遇到10则输出N/A
输入:
23
输出:
AD AE AF BD BE BF CD CE CF
输入:
10
输出:
N/A
下面写分析:
因为1、0的缘故和7、9的字母数为4这两方面的原因,我首先考虑采用枚举类来保存字母数据:
enum NumberEnum{ ONE(1), TWO(2,"ABC"), THREE(3,"DEF"), FOUR(4,"GHI"), FIVE(5,"JKL"), SIX(6,"MNO"), SEVEN(7,"PQRS"), EIGHT(8,"TUV"), NINE(9,"WXYZ"), ZERO(0), HASH("#"), ASTERISK("*"); public String getLetters() { return letters; } public Integer getNumber() { return number; } private Integer number; private String letters; NumberEnum(Integer number){ this.number = number; } NumberEnum(String letters) { this.letters = letters; } NumberEnum(Integer number,String letters) { this.number = number; this.letters = letters; } public static List<String> findLettersByNumber(int number) { if (number < 0 ) { throw new IllegalArgumentException("Wrong number input: " + number); } for (NumberEnum num : NumberEnum.values()) { if (Objects.equals(num.getNumber(),number)) { return new ArrayList<>(Arrays.asList(num.getLetters().split(""))); } } return null; } }
枚举类中包括一个根据数字获取对应的字母的方法。
根据题意这是在求多个集合的笛卡尔积,因为两集合的笛卡尔积用两层for循环即可实现
多个集合的笛卡尔积可以简化成多个两个笛卡尔积多起求笛卡尔积;
例如:
有集合X和Y,其笛卡尔积表示为X × Y
另有集合Z,那么X × Y × Z = (X × Y )× Z
一个数从前往后遍历每一个数字不是很好实现,而从后往前最后一位和倒数第二位可以分别表示为m%10和m/10%10
对于小于10的整数除1和0外,均有对应字母,因此对于2~9的数迭代第二层,递归的第二层就可以获取其对应字母List,然后计算出第二层迭代的结果,与倒数第二位前面的运算结果进行计算
例如:
对于输入为2345
其迭代表达式为:
d(s(23),d(s(4),s(5)))
d(s(4),s(5)) = GJ GK GL HJ HK HL IJ IK IL
s(23) = AD AE AF BD BE BF CD CE CF
那么d(s(23),d(s(4),s(5))) = ADGJ ADGK ADGL ADHJ ADHK ADHL ADIJ ADIK ADIL AEGJ AEGK AEGL AEHJ AEHK AEHL AEIJ AEIK AEIL AFGJ AFGK AFGL AFHJ AFHK AFHL AFIJ AFIK AFIL BDGJ BDGK BDGL BDHJ BDHK BDHL BDIJ BDIK BDIL BEGJ BEGK BEGL BEHJ BEHK BEHL BEIJ BEIK BEIL BFGJ BFGK BFGL BFHJ BFHK BFHL BFIJ BFIK BFIL CDGJ CDGK CDGL CDHJ CDHK CDHL CDIJ CDIK CDIL CEGJ CEGK CEGL CEHJ CEHK CEHL CEIJ CEIK CEIL CFGJ CFGK CFGL CFHJ CFHK CFHL CFIJ CFIK CFIL
业务逻辑实现:
private static String solutionOutput(int number) { if (number == 10) return "N/A"; return solution(number).stream().reduce((s1,s2)-> s1 + " " + s2 ).orElseThrow(NoSuchElementException::new); }
private static List<String> solution(int number) { if (number == 0 || number == 1) return new ArrayList<>(); List<String> letters = NumberEnum.findLettersByNumber(number); if (CollectionUtils.isNotEmpty(letters)) return letters; return descartes(solution(number/100),descartes(solution(number/10%10),solution(number%10))); } private static List<String> descartes(List<String> m,List<String> n) { List<String> result = new ArrayList<>(); if (m.isEmpty()) return n; if (n.isEmpty()) return m; for (String a : m) { for (String b : n) { result.add(a+b); } } return result; }

浙公网安备 33010602011771号