一道九宮格演算法面試題
阿新 • • 發佈:2019-02-18
前言
一前公司同事把此題放在群裡,求大家幫忙解答。
因為沒有其他條件和說明。我的第一印象就是:方格里應該填1~9整數中剩下的1~8,且不能重複。於是拿著筆進行了一通計算。。。後來發現無解。
接著,就想裡面的算術運算子(+、-、×、÷),不按優先順序,直接按先後順序來計算,如:a - b × c,當做(a - b) × c 來運算。最後得到如下結果:
5 8 9
7 6 4
3 2 1
為了鍛鍊下自己的演算法能力,後來用Java寫了份程式碼來測試:
public static void main(String[] args) {
nineBlockBox();
}
private static void nineBlockBox() {
List<int[]> result = compute();
printf("列印結果:\n");
for (int i = 0; i < result.size(); i++) {
printf("第%d組結果:\n", i+1);
int count = 0;
for (int a : result.get(i)) {
printf(a + "\t");
if (++count == 3) {
printf("\n" );
count = 0;
}
}
}
}
private static List<int[]> compute() {
// 九宮格位置:
// 0 1 2
// 3 4 5
// 6 7 8
// 條件
// ① (nb[0] + nb[1]) - 9 = 4
// ② (nb[3] - nb[4]) * nb[5] = 4
// ③ (nb[6] + nb[7]) - nb[8] = 4
// ④ (nb[0] + nb[3]) / nb[6] = 4
// ⑤ (nb[1] - nb[4]) * nb[7] = 4
// ⑥ ( 9 - nb[5]) - nb[8] = 4
List<int[]> list = new ArrayList<>();
int[] nb = new int[9];
for (int i = 1; i <= 9; i++) {
// 初始化數值
initArr(nb);
if (!isNumValid(nb, i)) {
continue;
}
nb[0] = i;
// ① (nb[0] + nb[1]) - 9 = 4
int temp = 4 + 9 - nb[0];
if (!isNumValid(nb, temp)) {
nb[0] = 0;
continue;
}
nb[1] = temp;
for (int j = 1; j <= 9; j++) {
if (!isNumValid(nb, j)) {
continue;
}
nb[5] = j;
// ⑥ ( 9 - nb[5]) - nb[8] = 4
temp = 9 - nb[5] - 4;
if (!isNumValid(nb, temp)) {
nb[5] = 0;
continue;
}
nb[8] = temp;
for (int k = 1; k <= 9; k++) {
if (!isNumValid(nb, k)) {
continue;
}
nb[3] = k;
// ② (nb[3] - nb[4]) * nb[5] = 4
// 4 = 1 * 4 = 2 * 2
temp = nb[3] - 4 / nb[5];
if (!isNumValid(nb, temp)) {
nb[3] = 0;
continue;
}
nb[4] = temp;
for (int m = 1; m <= 9; m++) {
if (!isNumValid(nb, m)) {
continue;
}
nb[6] = m;
// ③ (nb[6] + nb[7]) - nb[8] = 4
temp = 4 + nb[8] - nb[6];
if (!isNumValid(nb, temp)) {
nb[6] = 0;
continue;
}
nb[7] = temp;
// ④ (nb[0] + nb[3]) / nb[6] = 4
// ⑤ (nb[1] - nb[4]) * nb[7] = 4
if (((nb[0] + nb[3]) / nb[6] == 4) && ((nb[1] - nb[4]) * nb[7] == 4)) {
int[] result = new int[nb.length];
System.arraycopy(nb, 0, result, 0, nb.length);
list.add(result);
}
nb[6] = nb[7] = 0;
}
nb[3] = nb[4] = 0;
}
nb[5] = nb[8] = 0;
}
}
return list;
}
private static void initArr(int[] arr) {
Arrays.fill(arr, 0);
arr[2] = 9;
}
private static boolean isNumValid(final int[] arr, final int num) {
if (num < 1 || num > 9) {
return false;
}
for (int a : arr) {
if (a == num) {
return false;
}
}
return true;
}
列印結果:
後來百度得知這是一道騰訊校招筆試題。
正題
題目:
用0~100的整數填入以下方格中,使填入後的運算結果,滿足下圖所示的條件。求出所有解。
個人解答過程:
把每一個條件進行,並把相關的條件進行整合分析,最後根據整合結果寫程式碼。條件的分析在程式碼中(為了方便閱讀理解,沒有作優化,如i, j, k臨時變數完全可以去掉)
private static List<int[]> compute_100() {
// 九宮格位置:
// 0 1 2
// 3 4 5
// 6 7 8
// 條件
// ① a[0] + a[1] - 9 = 4
// ② a[3] - a[4] * a[5] = 4
// ③ a[6] + a[7] - a[8] = 4
// ④ a[0] + a[3] / a[6] = 4
// ⑤ a[1] - a[4] * a[7] = 4
// ⑥ 9 - a[5] - a[8] = 4
/*
分析
①:a[0] + a[1] = 13 --> a[0]∈[0,13], a[1]∈[0,13] ......⑦
②:a[3] >= 4
④:a[0] <= 4, a[6] != 0 +⑦--> a[0]∈[0,4],a[1]∈[9,13] ......⑧
⑤:a[1] >= 4 +⑧--> (a[4] * a[7])∈[5,9],即:a[4]∈[1,9],a[7]∈[1,9]
⑥:a[5] + a[8] = 5 --> a[5]∈[0,5], a[8]∈[0,5]
*/
List<int[]> list = new ArrayList<>();
int[] a = new int[9];
a[2] = 9;
for (int i = 0; i <= 4; i++) {
a[0] = i;
a[1] = 13 - i; // ① a[0] + a[1] - 9 = 4
for (int j = 0; j <= 5; j++) {
a[5] = j;
a[8] = 5 - j; // ⑥ 9 - a[5] - a[8] = 4
for (int k = 1; k <= 9; k++) {
a[4] = k;
a[3] = 4 + a[4] * a[5]; // ② nb[3] - nb[4] * nb[5] = 4
float temp = (a[1] - 4) / a[4]; // ⑤ nb[1] - nb[4] * nb[7] = 4
// 去小數
if (a[1] - a[4] * temp != 4f) {
continue;
}
a[7] = (int)temp;
a[6] = 4 + a[8] - a[7]; // ③ nb[6] + nb[7] - nb[8] = 4
if (a[6] != 0) {
// 去小數
if (a[0] + a[3] * 1f / a[6] == 4f) { // ④ nb[0] + nb[3] / nb[6] = 4
int[] result = new int[a.length];
System.arraycopy(a, 0, result, 0, a.length);
list.add(result);
}
}
}
}
}
return list;
}
列印結果只有一組: