在數論與演算法練習中,尋找「連續 6 個奇數皆為合數」的最小起始值 a,是一個經典的暴力搜尋題目。序列形式為 a, a+2, a+4, a+6, a+8, a+10,要求每一項皆為合數(非質數)。本文將詳細解析如何使用 Java 實作暴力演算法,並展示從 1 連續到 100 連續的完整執行日誌與效能數據。
採用試除法至平方根,時間複雜度 O(√n):
public static boolean isComposite(int num) {
if (num < 2) return false;
int sqrt = (int) Math.sqrt(num);
for (int i = 2; i <= sqrt; i++) {
if (num % i == 0) return true;
}
return false;
}
採用貪婪遞歸:找到滿足 k 連續的最小值後,直接以該值為起點搜尋 k+1 連續,大幅縮減搜尋空間。
public static List<Map<Integer, Integer>> searchConsecutive(int times, int start, boolean onlyStart) {
List<Map<Integer, Integer>> results = new ArrayList<>();
// 略過偶數、邊界檢查...
for (int i = start; i < Integer.MAX_VALUE; i += 2) {
boolean allComposite = true;
for (int j = 0; j < times; j++) {
if (!isComposite(i + 2 * j)) { allComposite = false; break; }
}
if (allComposite) {
Map<Integer, Integer> map = new HashMap<>();
map.put(times, i);
results.add(map);
// 遞歸搜尋下一層
results.addAll(searchConsecutive(times + 1, i, true));
break;
}
}
return results;
}
程式記錄了從 1 連續到 124 連續的完整搜尋過程,關鍵里程碑如下:
| 連續數 | 最小起始值 n | 耗時 (ms) | 累計耗時 (ms) |
|---|---|---|---|
| 6 | 115 | 0 | 1 |
| 10 | 31399 | 5 | 13 |
| 13 | 17051709 | 86082 | 100979 |
| 15 | 20831325 | 34772 | 135752 |
| 124 | 387096135 | 6650201 | 10265457 |
雖然暴力法能解決問題,但隨著連續數增加,效能瓶頸明顯。可考慮以下優化:
程式包含三個核心類別:
ZhishuTest:主類,含合數判斷、遞歸搜尋、效能計時ThreadLocal 管理執行緒本地節點AtomicReferenceFieldUpdater 實作無鎖佇列(CLH 鎖變體)完整原始碼已整合於上方片段,可直接複製編譯執行。建議搭配 -Xmx2g 等 JVM 參數執行長時間搜尋任務。