
1. 二分查找在真實工程里為什么總翻車二分查找算法也叫折半查找核心思路是分而治之每次拿中間元素和目標(biāo)比較排除掉一半?yún)^(qū)間。聽起來簡單到不需要動腦但我在后端項目里見過太多因為二分查找寫錯邊界導(dǎo)致線上數(shù)據(jù)錯亂的案例。它適合誰算法入門的學(xué)習(xí)者、需要手寫查找邏輯的后端開發(fā)者、以及準(zhǔn)備面試但總在low high還是low high上卡殼的人。問題不在思想而在落地細(xì)節(jié)。真實工程里數(shù)組可能長達千萬級mid (low high) / 2在極端情況下會整型溢出目標(biāo)值可能不存在返回-1還是插入位置需要明確重復(fù)元素場景下你要的是第一個匹配還是任意一個匹配直接決定模板怎么寫。這些邊界條件才是二分查找從課本走向生產(chǎn)的分水嶺。這篇內(nèi)容我會交付三樣?xùn)|西可直接復(fù)制的二分查找模板含左右邊界與溢出防護、一套能跑起來的測試用例配置以及通過 TaoToken 統(tǒng)一 Key/API 通道調(diào)用驗證腳本的settings.json骨架。你可以在本地快速復(fù)現(xiàn)驗證查找邏輯的正確性和效率而不是停留在“看起來懂了”。2. TaoToken 前置準(zhǔn)備統(tǒng)一 Key 與 API 通道在開始寫驗證腳本之前先把調(diào)用通道準(zhǔn)備好。TaoToken 在這里的角色是統(tǒng)一入口你不需要為每個模型或工具單獨維護一套鑒權(quán)和地址用一個 Key 就能走通模型對話、編碼計劃、控制臺管理等場景。對于二分查找這種需要反復(fù)跑測試、對比不同實現(xiàn)輸出結(jié)果的場景統(tǒng)一通道能省掉大量切換成本。你需要先拿到 API Key。進入控制臺后創(chuàng)建密鑰建議按項目命名比如binary-search-verify方便后續(xù)排查。創(chuàng)建完成后把 Key 保存到本地環(huán)境變量或配置文件里不要硬編碼進源碼。關(guān)鍵地址記好這幾個官網(wǎng)入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 基地址https://taotoken.net/api模型對話https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodels編碼計劃https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcodingplan控制臺https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentconsoleAPI Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapikeys接入文檔https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc注意API 基地址不帶 UTM 參數(shù)直接使用https://taotoken.net/api即可。其余 deep link 建議帶上 UTM便于你回溯來源。如果你后續(xù)要做長期編碼或 Agent 類任務(wù)可以關(guān)注 Coding Plan如果只是驗證模型輸出走模型對話頁面即可。二分查找的驗證腳本屬于“接入 驗證”混合場景所以 API Keys 和接入文檔是你最該先看的兩個入口。3. 可復(fù)制的二分查找模板與配置3.1 標(biāo)準(zhǔn)模板溢出防護與邊界處理先給一個我實測下來最穩(wěn)的迭代版本。核心改動有兩處mid用low (high - low) / 2防溢出循環(huán)條件用low high保證區(qū)間閉合。#include iostream #include vector using namespace std; // 標(biāo)準(zhǔn)二分查找返回目標(biāo)下標(biāo)不存在返回 -1 int binarySearch(const vectorint nums, int target) { int low 0; int high (int)nums.size() - 1; while (low high) { int mid low (high - low) / 2; // 防溢出 if (nums[mid] target) { return mid; } else if (nums[mid] target) { low mid 1; } else { high mid - 1; } } return -1; }這個版本解決的是“找任意一個匹配”。但工程里更常見的是找左邊界和右邊界比如統(tǒng)計某個值出現(xiàn)的次數(shù)、找第一個大于等于目標(biāo)的位置。3.2 左邊界與右邊界模板左邊界找第一個等于 target 的下標(biāo)。關(guān)鍵點是命中后不立即返回而是收縮右邊界繼續(xù)往左找。// 左邊界第一個等于 target 的下標(biāo)不存在返回 -1 int lowerBound(const vectorint nums, int target) { int low 0, high (int)nums.size() - 1; int ans -1; while (low high) { int mid low (high - low) / 2; if (nums[mid] target) { if (nums[mid] target) ans mid; high mid - 1; } else { low mid 1; } } return ans; }右邊界找最后一個等于 target 的下標(biāo)。命中后收縮左邊界。// 右邊界最后一個等于 target 的下標(biāo)不存在返回 -1 int upperBound(const vectorint nums, int target) { int low 0, high (int)nums.size() - 1; int ans -1; while (low high) { int mid low (high - low) / 2; if (nums[mid] target) { if (nums[mid] target) ans mid; low mid 1; } else { high mid - 1; } } return ans; }三個模板的差異用表格對照更清楚場景循環(huán)條件mid 更新命中后動作返回值任意匹配low highlow(high-low)/2立即返回下標(biāo)或 -1左邊界low highlow(high-low)/2記錄并收縮 high首個下標(biāo)或 -1右邊界low highlow(high-low)/2記錄并收縮 low末個下標(biāo)或 -13.3 測試用例配置光有模板不夠得有能跑的測試。下面這組用例覆蓋了空數(shù)組、單元素、重復(fù)元素、目標(biāo)不存在、目標(biāo)在兩端等邊界。#include cassert void runTests() { vectorint empty {}; assert(binarySearch(empty, 5) -1); vectorint single {7}; assert(binarySearch(single, 7) 0); assert(binarySearch(single, 3) -1); vectorint dup {1, 2, 2, 2, 3, 4, 5}; assert(binarySearch(dup, 2) ! -1); assert(lowerBound(dup, 2) 1); assert(upperBound(dup, 2) 3); vectorint normal {3, 5, 9, 14, 17, 23, 29, 33, 37}; assert(binarySearch(normal, 33) 7); assert(binarySearch(normal, 100) -1); assert(lowerBound(normal, 3) 0); assert(upperBound(normal, 37) 8); cout All tests passed. endl; }3.4 settings.json 骨架通過 TaoToken 調(diào)用驗證腳本如果你想讓驗證腳本通過統(tǒng)一通道調(diào)用模型來生成或校驗測試用例可以用下面這個settings.json骨架。把 Key 放到環(huán)境變量里配置文件只引用變量名。{ provider: taotoken, api_base: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, model: your-preferred-model, timeout_ms: 30000, retry: { max_attempts: 3, backoff_ms: 500 }, tasks: { verify_binary_search: { prompt_template: 給定數(shù)組 {array} 和目標(biāo) {target}請判斷二分查找返回下標(biāo)是否正確并說明邊界處理是否合理。, output_format: json } } }這個骨架的作用是你的本地測試腳本跑完斷言后可以把失敗用例的數(shù)組和目標(biāo)值拼進 prompt通過 TaoToken 通道請求模型輔助分析邊界問題。注意api_base用不帶 UTM 的地址api_key_env指向你設(shè)置的環(huán)境變量名。4. 驗證請求與成功結(jié)果配置好之后先做一次最小驗證。用 curl 發(fā)一個請求確認(rèn)通道能通。export TAOTOKEN_API_KEY你的Key curl -s -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: your-preferred-model, messages: [ {role: user, content: 數(shù)組 [1,2,2,2,3] 中查找 2 的左邊界下標(biāo)是多少只返回數(shù)字。} ] }成功時你會拿到一個 JSON 響應(yīng)choices[0].message.content里應(yīng)該是1。這說明通道通了模型也能正確理解左邊界語義。接著跑本地測試。編譯并執(zhí)行g(shù) -stdc17 -O2 binary_search.cpp -o bs_test ./bs_test預(yù)期輸出All tests passed.如果斷言全部通過說明三個模板在邊界場景下行為正確。我試過把mid (low high) / 2換回去在超大數(shù)組模擬下會觸發(fā)溢出斷言直接掛掉這就是為什么要堅持用low (high - low) / 2。性能驗證方面可以用chrono計時對千萬級有序數(shù)組做 100 萬次查找標(biāo)準(zhǔn)二分通常在毫秒級完成。如果你發(fā)現(xiàn)耗時異常先檢查是不是每次查找都重新拷貝了數(shù)組。5. 本篇常見錯排查第一個高頻錯誤是死循環(huán)。典型癥狀是程序卡住不返回。原因通常是low mid或high mid沒有加減一導(dǎo)致區(qū)間不收縮。記住命中后要么返回要么收縮邊界時必須mid ± 1。第二個是漏掉等號。while (low high)在單元素數(shù)組上會直接跳過循環(huán)返回錯誤結(jié)果。除非你明確用的是左閉右開區(qū)間寫法否則統(tǒng)一用low high。第三個是溢出。(low high)在low和high都接近INT_MAX時會溢出成負(fù)數(shù)mid變成非法下標(biāo)。防護寫法就是low (high - low) / 2。第四個是重復(fù)元素返回不確定。標(biāo)準(zhǔn)模板返回的是任意一個匹配如果你需要第一個或最后一個必須換成左邊界或右邊界模板。用錯模板會導(dǎo)致統(tǒng)計次數(shù)、范圍查詢結(jié)果偏差。第五個是空數(shù)組未處理。high nums.size() - 1在空數(shù)組時是-1循環(huán)條件low high為假直接返回-1這其實是正確的。但如果你寫成high nums.size()再配合左閉右開就要小心越界。第六個是通道配置錯誤。如果 curl 返回 401檢查 Key 是否設(shè)置正確、環(huán)境變量是否導(dǎo)出如果返回 404檢查api_base是否誤加了路徑或 UTM 參數(shù)。接入文檔里有完整的錯誤碼說明遇到問題先對照文檔排查。6. 繼續(xù)深入的方向二分查找的工程落地遠(yuǎn)不止這三個模板。你可以在此基礎(chǔ)上擴展旋轉(zhuǎn)有序數(shù)組的查找、二維矩陣的二分、以及基于二分的答案空間搜索比如求最小最大值問題。這些場景的共同點是邊界條件的處理邏輯需要根據(jù)“單調(diào)性”重新推導(dǎo)而不是套模板。如果你想把驗證流程自動化可以把測試用例和 TaoToken 通道結(jié)合起來讓腳本在斷言失敗時自動請求模型分析原因形成閉環(huán)。長期做編碼類任務(wù)的話Coding Plan 會比單次調(diào)用更省心。需要管理多個項目的 Key 時控制臺里的 API Keys 頁面可以按項目隔離。最后留一個實用技巧寫完任何二分查找先用空數(shù)組、單元素、全相同元素、目標(biāo)在兩端這四組用例跑一遍。這四組能過基本就不會有邊界翻車。