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

相關文章
相關標籤/搜索