该数组做为三角的底层,已底层数据生成一个层,新车与底层的数据规则以下: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