日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

90%的程序员都写错的算法-二分查找万能模版

發布時間:2025/3/19 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 90%的程序员都写错的算法-二分查找万能模版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

新的角度看二分

  • 二分就是將數組分為兩段
  • 因此,問題的最終目標是找出藍紅邊界

樸素算法

  • 紅色指針一開始指向最右超出范圍處,隨后不斷向左移動,直到找到藍紅邊界;或者藍色指針…
  • 時間復雜度O(n)O(n)O(n)

二分查找


  • 紅藍指針的移動其實代表著紅藍區域的拓展。那么,有什么更快拓展的方式呢?由于數組本身有序…便可以快速拓展紅色 或 藍色區域
  • 數組下標有效范圍[0,n?1][0,n - 1][0,n?1],因此,初始時l = -1, r = n;
  • 循環的結束條件是l + 1 != r,因為l指向藍色邊界最右邊,r指向紅色邊界最左邊,當l + 1 == r時整個數組已經由灰色未知被劃分完畢
  • 如果m是紅色區域,直接r = m;同理…
  • 最后結果返回l還是r要看情況

細節1.為什么l的初始值為-1,r的初始值為n

  • 假如最終整個數組都該是紅色區域,如果l初始化為0,l一開始就處在紅色區域內,這會造成錯誤;同理…

細節2.m是否始終處于[0,n)以內

  • 只有處在這個區間以內,m才是有意義的
  • 先看m的下界,由于m = (l + r) / 2(向下),因此如果我們想讓m盡可能小,就要l和r盡可能小,l的最小值是初始值-1,r如果能進入循環體,最小值是1(不是0),因此m最小值為0
  • 再看m上界,同理,r的最大值為n,l如果要進入循環體,最大值為n - 2,因此m最大值為n - 1

細節3.更新指針時,能不能寫成l = m + 1或者r = m - 1


  • 如果剛好m指向藍色區域的最后一個位置,l如果變為m + 1,就錯了;同理…

細節4.會不會陷入死循環

  • 分別考慮l + 1 == r l + 2 == r l + 3 == r的情況
  • l + 1 == r,退出循環
  • l + 2 == r,也就是它們之間隔一個元素,當進入循環體時,m就是它們之間隔著的那個元素,接下來,要么將l設置成m,要么將r設置成m,也就是說,在循環體結束時,l的下一個元素一定是r,會回歸到第一種情況并退出循環體
  • l + 3 == r,會回歸到第二種情況或者回歸到第一種情況

例子 與 c++庫函數

  • lower_bound對應大于等于
  • upper_bound對應大于

一般流程

  • 后處理指的是 例如 只有藍色區域/紅色區域的返回值處理問題(需要特判)等

如果沒有藍色區域或者紅色區域

  • 那么l或者r會不在有效范圍內
  • 最后結果特判,l的初始值為-1,r的初始值為n

浮點數的二分

  • 題目 :通過二分查找的方式計算2\sqrt{2}2?,要求誤差小于10?610^{-6}10?6
  • 退出循環的條件為r - l <= 1e-8
  • 要求誤差小于10?610^{-6}10?6,相當于 結果保留6位小數;這樣,循環退出的條件是10?810^{-8}10?8,而輸出則是六位小數
#include <iostream> #include <iomanip> using namespace std; int main() {double l = -10000, r = 10000;while (r - l > 1e-8){double mid = (l + r) / 2;if (mid * mid >= 2) r = mid;else l = mid;} // printf("%.6lf\n", l);cout << fixed << setprecision(6) << l << endl;return 0; }

總結

以上是生活随笔為你收集整理的90%的程序员都写错的算法-二分查找万能模版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。