背景
異或(xor,運算符號^
):按位計算,同0異1,1 ^ 0 = 1
,1 ^ 1 = 0
,如此。
現定義等差數列 1, 2, ... , n
的 異或和 爲 f(n) = 1 ^ 2 ^ ... ^ n
,求f(n)的值。
實現
我們很容易想到質樸的實現如下:
int func(int n) {
int xor_sum = 0;
for (int i = 1; i <= n; ++i) {
xor_sum ^= i;
}
return xor_sum;
}
時間複雜度O(n),空間複雜度此處沒有太大必要討論。
通式
聯想到等差數列的四則運算都是有求和公式的,那麼異或運算有沒有呢?直接這麼看也看不出來,先輸出個十來項看看規律:
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
// 1 3 0 4 1 7 0 8 1 11 0 12 1 15 0 16 1 19
註釋中分別是從第1項到第18項的異或和。這個規律其實非常明顯了,拋開前2個結果不看,後面4個爲一組,定義爲m組,通式如下:
// n=3, 0 n=7, 0 n=4m-1, 0
// n=4, 4 n=8, 8 n=4m, 4m
// n=5, 1 n=9, 1 n=4m+1, 1
// n=6, 7 n=10, 11 n=4m+2, 4m+3
從n>=3開始,後面的異或和的取值都是固定的常量或者公式求得。優化後實現如下:
int func(int n) {
switch (n) {
case 1: return 1;
case 2: return 3;
default:
int r = n % 4;
switch (r) {
case 0: return r;
case 1: return 1;
case 2: return (n - 2) + 3;
default: return 0;
}
}
}
時間複雜度O(1) ,部分代碼爲了體現公式沒有精簡,主要操作就是取餘。
這樣能提升不少性能。