該數組做爲三角的底層,已底層數據生成一個層,新車與底層的數據規則以下:java
兩個數相同,則新層的數字與下一層同樣,兩個數不一樣,則新一層的數據與兩個數字都不相同。git
示例:數組
1函數
1 1code
2 3 2blog
2 2 1 3it
3 1 3 2 1class
先來個暴力解法,效率
方案1:遍歷
public void digitalPredictor(int[] array) { for (int i = array.length; i > 0; i--) { for (int j = 0; j < i - 1; j++) { if (array[j] != array[j + 1]) { array[j] = array[j] ^ array[j + 1]; } } } };
顯然這個方法效率很低。計算size=1024*1024,無法算。
對生成的三角,視爲一個二元數組,a[size][size]
1
1 1
2 3 2
2 2 1 3
3 1 3 2 1
觀察三角,發現以下狀況:
設運算符爲¥
當SIZE=4時,
a[3][0]=a[0][0]¥a[0][3] ,即只須要知道a[0][0]和a[0][3]就能知道Size爲4狀況下的三角頂點值。
對全部Size=4狀況進行遍歷,能夠驗證該猜測。
而對與任意Size內的 Size爲4的小三角的三個點 a[s][t] a[s+3][t] a[s][t+3],都知足
a[s][t]=a[s+3][t]¥a[s][t+3]
即獲得以下公式:
a[3^k+t][i] = a[t][i]¥a[t][i+3^k]
或者
a[s][t] = a[s-3^k][t]¥a[s-3^k][t+3^k]
即,對於與這個三角(底層爲0層)任意知足層數=3^N的任意一個位置i,都能直接從0層取對應的兩個數獲得結果,能夠計算出3^n層的全部數字。
方案2:
public static void my2(int[] array, int length) { if (length < 4) { for (int i = length; i > 0; i--) { for (int j = 0; j < i - 1; j++) { if (array[j] != array[j + 1]) { array[j] = array[j] ^ array[j + 1]; } } } System.out.println("最後" + length + "層結束"); return; } int base = 1; int temp = length-1; while (temp / 3 >= 1) { base *= 3; temp /= 3; } System.out.println("升高了" + base + "層"); // 須要計算 for (int i = 0; i <= length - 1 - base; i++) { array[i] = array[0] == array[base + i] ? array[0] : array[0] ^ array[base + i]; } my2(array, length - base); }
最後結果爲array[0]
計算size=1024*1024的cost=20~30ms
在計算3^n層的時候,真的須要把全部都計算出來嗎?顯然不須要,計算過程當中作了不少無用的計算。
若是肯定了跳躍計算的路徑,能夠知道全部須要計算的點。
以size=17舉例:
能夠看到,從0層跳到9層,9層跳到12層,12層到15層,15層到16層結束,中間只須要計算通過的那些點。
方案3:
public static int my3(int[] array) { int[] step = new int[50]; int deep = 0; int length = array.length; if (length == 1) { return array[0]; } while (length > 1) { int base = 1; int temp = length - 1; while (temp / 3 >= 1) { base *= 3; temp /= 3; } step[deep] = base; deep++; length -= base; } return fx(array.length - 1, 0, array, step, deep); } private static int fx(int r, int c, int[] arr, int[] step, int deep) { if (r == 0) { return arr[c]; } else { return func(fx(r - step[deep], c, arr, step, deep - 1), fx(r - step[deep], c + step[deep], arr, step, deep - 1)); } } private static int func(int a, int b) { return a == b ? a : a ^ b; }
計算size=1024*1024,cost=1ms~2ms