重建与数字子序列匹配的最小数字序列的有效方法
背景:
通过一个游戏使用两个小数字 firstStep 和 secondStep 生成的一个数字。这个数字的一些数字(位数)丢失了!
他们仍然保留了一部分数字,叫做 puzzleNumber。这就像是一个拼图——有些数字还在,但其他一些缺失了。任务是要找出在部分数字丢失之前,完整的数字可能是什么。
游戏规则如下:
从分数 0 开始。
你可以随意多次地将 firstStep 或 secondStep 加到分数上。
每次加完后,只记录分数的最后一位数字(这叫做单位数,例如 123 中的 3)。
持续记录这些数字,形成一个大数字。
现在想象你这样做得到了一个数字,但有人擦除了一些数字。你现在看到的是 puzzleNumber。
现在的任务是:找到最小的可能完整数字,使得 puzzleNumber 可以通过从这个完整数字中删除一些数字(即 puzzleNumber 是完整数字的子序列)而得到。如果游戏中没有任何数字可以做到这一点,则返回 “-1”。
方案:
public static String solve(String puzzleNumber, int firstStep, int secondStep) {int inc = 1; // incrementif (firstStep == 5 && secondStep == 5) {for (int i = 0; i < puzzleNumber.length(); i++)if ((puzzleNumber.charAt(i) - '0') % 5 != 0)return "-1";} else if (firstStep % 2 == 0 && secondStep % 2 == 0) {for (int i = 0; i < puzzleNumber.length(); i++)if ((puzzleNumber.charAt(i) - '0') % 2 != 0)return "-1";inc = 2;}StringBuilder sb = new StringBuilder();if (firstStep == secondStep) {for (int i = 0, d = 0; i < puzzleNumber.length(); i++)do {d = (d + firstStep) % 10;sb.append(d);} while (d != puzzleNumber.charAt(i) - '0');}else {int[][] lookup = new int[10][10];for (int i = 0; i < 10; i += inc)for (int j = 0; j < 10; j += inc)lookup[i][j] = 10;for (int i = 0; i < 10; i += inc) {lookup[i][(i + firstStep) % 10] = (i + firstStep) % 10;lookup[i][(i + secondStep) % 10] = (i + secondStep) % 10;}boolean skipped = true;while (skipped) {skipped = false;int[][] backup = new int[10][];for (int i = 0; i < 10; i += inc)backup[i] = lookup[i].clone();for (int cur = 0; cur < 10; cur += inc)for (int next = 0; next < 10; next += inc)if (backup[cur][next] == 10) {int cur1 = (cur + firstStep) % 10;int cur2 = (cur + secondStep) % 10;if (backup[cur1][next] + backup[cur2][next] == 20)skipped = true;else if (backup[cur2][next] == 10)lookup[cur][next] = cur1;else if (backup[cur1][next] == 10)lookup[cur][next] = cur2;elselookup[cur][next] = Math.min(cur1, cur2);}}for (int i = 0, d = 0; i < puzzleNumber.length(); i++)do {d = lookup[d][puzzleNumber.charAt(i) - '0'];sb.append(d);} while (d != puzzleNumber.charAt(i) - '0');}return sb.toString();}