在回溯算法的剪枝操作中:
if (sum + candidates[i] > target) break;
這個 break
既不等效于 return
,也不會終止整個回溯過程。它只會終止當前層循環的后續迭代,而不會影響其他分支的回溯。讓我用圖解和示例詳細說明:
🧩 執行流程對比
1. 使用 break
的流程:
for (int i = start; i < candidates.length; i++) {if (sum + candidates[i] > target) break; // 終止當前層循環// ... 遞歸調用 ...
}
2. 使用 return
的流程:
for (int i = start; i < candidates.length; i++) {if (sum + candidates[i] > target) return; // 終止整個函數// ... 遞歸調用 ...
}
🌳 樹形結構圖解(以 candidates=[2,3,6,7], target=7 為例)
當前層:start=0, sum=0
├─ i=0: 選2 → 進入下層(sum=2)
├─ i=1: 選3 → 進入下層(sum=3)
├─ i=2: 選6 → sum+6=6<7 → 繼續
└─ i=3: 選7 → sum+7=7 → 有效組合
當處理到 i=2(值=6)時:
-
break
的情況:
僅跳過當前層后續的 i=3(值=7),但已處理的 i=0,1,2 的分支會繼續執行 -
return
的情況:
直接終止整個當前函數,包括:- 跳過 i=3(值=7)
- 終止已處理的 i=2 分支的后續遞歸
- 終止已處理的 i=1 分支的后續遞歸
- 終止已處理的 i=0 分支的后續遞歸
🔍 為什么必須用 break
而不是 return
?
1. 剪枝目標不同:
break
只剪當前層后續的無效分支return
會剪當前層所有分支(包括已開始但未完成的)
2. 排序特性的利用:
數組已排序(升序),所以當 sum + candidates[i] > target
時:
- 當前索引 i 之后的值都更大 → 肯定都超過 target
- 但當前索引 i 之前的值可能還有有效組合
? 正確剪枝示例
假設當前層:sum=5, candidates=[1,2,3,9,10], target=7
i=0: 5+1=6<7 → 繼續遞歸
i=1: 5+2=7==7 → 找到有效組合
i=2: 5+3=8>7 → break
// 跳過9和10,但保留已處理的1和2
?? 錯誤使用 return
的后果
i=0: 5+1=6<7 → 繼續遞歸
i=1: 5+2=7==7 → 找到有效組合
i=2: 5+3=8>7 → return // 災難!
// 將丟失1和2分支的后續遞歸結果
💡 關鍵總結
操作 | 影響范圍 | 適用場景 |
---|---|---|
break | 僅終止當前層后續循環 | 排序后剪枝后續無效值 |
return | 終止整個當前函數 | 確定后續所有分支都無效時 |
continue | 跳過當前迭代繼續下一個 | 需要跳過特定值但繼續嘗試其他值 |
在組合求和的剪枝中,break
是最精確的工具:
- 利用數組有序性
- 僅跳過確定無效的后續值
- 保留已處理分支的遞歸
- 最大化減少無效計算同時保證結果完整
這就是為什么我們使用 break
而不是 return
——它像精準的外科手術刀,只切除病變部位而不傷及健康組織!