DigitalPredictor数字预测

  • 给定一个数组,数组包含无数个1,2,3.

    该数组做为三角的底层,已底层数据生成一个层,新车与底层的数据规则以下:java

    两个数相同,则新层的数字与下一层同样,两个数不一样,则新一层的数据与两个数字都不相同。git

    示例:数组

                            1函数

                          1    1code

                        2    3    2blog

                    2    2     1    3it

                  3    1    3    2     1class

 

  • 函数输出结果为三角顶层的值。输入数组长度N(1<N<1024*1024),内容只会有1,2,3

 

先来个暴力解法,效率

方案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

相关文章
相关标签/搜索