最直觀寫法:
int isPrime(int n) {
int i;
for (i = 2; i < n; i++)
if (n % i == 0) break;
return i >= n;
}
平方根優化:
int isPrime(int n) {
int i, s = (int)(sqrt((double)n) + 0.01);
for (i = 2; i <= s; i++)
if (n % i == 0) break;
return i > s;
}
消除偶數:
int isPrime(int n) {
int i, s = (int)(sqrt((double)n) + 0.01);
if (n <= 3) return 1;
if (n % 2 == 0) return 0;
for (i = 3; i <= s; i += 2)
if (n % i == 0) break;
return i > s;
}
終極優化:所有大於 4 的質數,除以 6 餘數只能是 1 或 5(即 6k±1 形式)。步長在 2、4 間切換(5→+2→7→+4→11→+2→13...):
int isPrime(int n) {
int i, s = (int)(sqrt((double)n) + 0.01), step = 4;
if (n <= 3) return 1;
if (n % 2 == 0) return 0;
if (n % 3 == 0) return 0;
for (i = 5; i <= s; i += step) {
if (n % i == 0) break;
step ^= 6; // 異或切換 2↔4:2^4=6, 6^2=4, 6^4=2
}
return i > s;
}
思考題:如何構造三值或四值循環步長?
傳統上下拆分打印代碼冗餘難讀。利用對稱性:以中心為 (0,0),輸出星號的座標滿足 |x| + |y| <= size。雙重迴圈從 -size 到 size,取絕對值即得對稱:
void print(int size) {
int x, y;
for (y = -size; y <= size; y++) {
for (x = -size; x <= size; x++) {
if (abs(x) + abs(y) <= size) putchar('*');
else putchar(' ');
}
putchar('\n');
}
}
變體:
== size;putchar('A' + (size - abs(x) - abs(y)));3×3 幻方:
4 3 8 9 5 1 2 7 6
向右複製 5 次、向下 3 次展開,藍色數字走向呈現規律。任意任意 n+1 的座標(左上角為 0,0):
x = 2 + n + n / 3;
y = 1 + n - n / 3;
推廣至任意奇數 size(整除):
x = size/2 + 1 + n + n/size;
y = size/2 + n - n/size;
複雜雙重迴圈化為單迴圈:
#define SIZE 5
int main() {
int x, y, i, sqSize = SIZE*SIZE, hSize = SIZE/2;
int sqMap[SIZE][SIZE];
for (i = 0; i < sqSize; i++) {
x = hSize + 1 + i + i/SIZE;
y = hSize + i - i/SIZE;
sqMap[y%SIZE][x%SIZE] = i + 1;
}
// 輸出...
}
比網上常見魔方陣代碼短小許多。
題目:"abcdefg" 循環左移 2 位 → "cdefgab",限 O(1) 空間。
反轉字串無需額外陣列(頭尾交換)。三次反轉法:
// 反轉 [st, ed)
void str_rev(char* st, char* ed) {
for (--ed; st < ed; ++st, --ed) {
char c = *st; *st = *ed; *ed = c;
}
}
// 循環左移 n 位
char* str_shl(char* st, char* ed, int n) {
str_rev(st, &st[n]); // 反轉前 n
str_rev(&st[n], ed); // 反轉後段
str_rev(st, ed); // 整體反轉
return st;
}
驗證:"abcdefghijklmnopqrstuvwxyz" 左移 6 位 → "ghijklmnopqrstuvwxyzabcdef"。
原理:分兩段(前 n、其餘),分別反轉再整體反轉 = 循環左移(先整體再分段 = 循環右移)。
—— 作者:Csdn_zc 的專欄