在java坛给人做了一道题目:
在下面十进制算术问题中,十个(以内)不同字母的每一个代表着一个0-9中的数字,写出
一个程序发现所有的可能解决的方案:
MARK A=1 W=2 N=3 R=4 E=5 9147
+ ALLEN L=6 K=7 L=8 M=9 S=0 +16653
________ --------------
WEISS 25800
有些要承认,一开始着手写的时候,居然没有看出这其实就是一个排列组合问题——从10(数字是0到9十个)中抽出X个(X是字母的个数),实在是很失败。所以后来在网上发现一些排列组合问题的好方法,就非常后悔自己浪费了很多时间。
import
java.util.HashMap;
import
java.util.HashSet;
import
java.util.Iterator;
public
class
Test
...
{
public static void main(String[] strs) ...{
String str1 = "MARK";
String str2 = "ALLEN";
String str3 = "WEISS";
printResult(str1, str2, str3);
}
public static void printResult(String str1, String str2, String str3) ...{
HashSet hashSetChar = new HashSet();
for (int i = 0; i < str1.length(); i++) ...{
hashSetChar.add(str1.charAt(i));
}
for (int i = 0; i < str2.length(); i++) ...{
hashSetChar.add(str2.charAt(i));
}
for (int i = 0; i < str3.length(); i++) ...{
hashSetChar.add(str3.charAt(i));
}
if (hashSetChar.size() > 10) ...{
System.out.println("counter of Character > 10, no result.");
}
HashMap hashMapC2D = new HashMap();
HashSet hashSetDigit = new HashSet();
Object[] characters = hashSetChar.toArray();
int i = 0;
for (; i < characters.length; i++) ...{
hashMapC2D.put(characters[i], i);
hashSetDigit.add(i);
}
System.out.println("start...");
while (i >= 0) ...{
if (i == characters.length) ...{
if (getLongFromString(str1, hashMapC2D)
+ getLongFromString(str2, hashMapC2D) == getLongFromString(
str3, hashMapC2D)) ...{
System.out.println(toStringHashMapC2D(hashMapC2D));
}
i--;
}
int digit = -1;
Integer intDigit = (Integer) hashMapC2D.get(characters[i]);
if (intDigit != null) ...{
digit = intDigit.intValue();
hashMapC2D.remove(characters[i]);
hashSetDigit.remove(digit);
}
if (digit == 9) ...{
i--;
} else ...{
while (digit++ < 9) ...{
if (!hashSetDigit.contains(digit)) ...{
break;
}
}
if (digit == 10)
i--;
else ...{
hashMapC2D.put(characters[i], digit);
hashSetDigit.add(digit);
i++;
}
}
}
System.out.println("end.");
}
private static String toStringHashMapC2D(HashMap hashMapC2D) ...{
StringBuffer sb = new StringBuffer();
Iterator iteratorKey = hashMapC2D.keySet().iterator();
while (iteratorKey.hasNext()) ...{
Character character = (Character) iteratorKey.next();
Integer digit = (Integer) hashMapC2D.get(character);
sb.append(character);
sb.append("=");
sb.append(digit);
sb.append(", ");
}
sb.delete(sb.length()-2, sb.length());
return sb.toString();
}
public static long getLongFromString(String str, HashMap hashMapC2D) ...{
long value = 0;
for (int i = 0; i < str.length(); i++) ...{
value += ((Integer) (hashMapC2D.get(str.charAt(i)))).intValue();
if (i < str.length() - 1)
value *= 10;
}
return value;
}
}
执行结果如下:
start...
E=0, W=2, A=1, S=5, R=4, L=7, M=3, N=6, I=8, K=9
E=0, W=2, A=1, S=5, R=4, L=7, M=3, N=9, I=8, K=6
E=0, W=9, A=8, S=2, R=1, L=6, M=3, N=5, I=4, K=7
E=0, W=9, A=8, S=2, R=1, L=6, M=3, N=7, I=4, K=5
E=2, W=6, A=5, S=0, R=7, L=8, M=3, N=1, I=4, K=9
E=2, W=6, A=5, S=0, R=7, L=8, M=3, N=9, I=4, K=1
E=3, W=2, A=1, S=4, R=0, L=7, M=6, N=5, I=8, K=9
E=3, W=2, A=1, S=4, R=0, L=7, M=6, N=9, I=8, K=5
E=3, W=6, A=5, S=1, R=7, L=4, M=8, N=2, I=0, K=9
E=3, W=6, A=5, S=1, R=7, L=4, M=8, N=9, I=0, K=2
E=4, W=3, A=2, S=6, R=1, L=8, M=5, N=7, I=0, K=9
E=4, W=3, A=2, S=6, R=1, L=8, M=5, N=9, I=0, K=7
E=5, W=2, A=1, S=0, R=4, L=6, M=9, N=3, I=8, K=7
E=5, W=2, A=1, S=0, R=4, L=6, M=9, N=7, I=8, K=3
E=5, W=2, A=1, S=3, R=7, L=8, M=6, N=4, I=0, K=9
E=5, W=2, A=1, S=3, R=7, L=8, M=6, N=9, I=0, K=4
E=6, W=3, A=2, S=5, R=9, L=7, M=8, N=1, I=0, K=4
E=6, W=3, A=2, S=5, R=9, L=7, M=8, N=4, I=0, K=1
E=6, W=5, A=4, S=0, R=3, L=7, M=8, N=1, I=2, K=9
E=6, W=5, A=4, S=0, R=3, L=7, M=8, N=9, I=2, K=1
end.
题目没有任何难度(不过到现在我仍然自责:没有在一开始就发现这是个简单的组合问题),程序也没有任何技巧。
唯一的关键是while (i > = 0) {}循环--用一个循环和一个变量实现了回溯算法。
本来,排列的算法用递归的话,程序会更清晰,但是考虑到资源和性能问题,同时为了练练手,还是用循环做了。
当然,把回溯或者单函数递归的程序,改写成简单循环,本来也没有任何技巧可言,是程序员考试和
高级程序员考试的基本功。