iT邦幫忙

2025 iThome 鐵人賽

DAY 7
3

https://ithelp.ithome.com.tw/upload/images/20250921/20177944ITCCdHLRBs.jpg

https://ithelp.ithome.com.tw/upload/images/20250921/20177944aCR5c8wWTD.jpg

https://ithelp.ithome.com.tw/upload/images/20250921/20177944VTCBr1kvJh.jpg

class Solution{
public:
    int search(vector<int>& a,int t){//主函式;a旋轉.互異.升序陣列
        int l=0,r=(int)a.size()-1;//初始化為整段
        while(l<=r){//區間未空持續二分
            int m=(l+r)>>1; // 本題無溢位風險
            if(a[m]==t) return m;
            if(a[l]<=a[m]) (a[l]<=t && t<a[m])? r=m-1: l=m+1;//左半單調有序;若t在[a[l],a[m))收右,否丟到右半
            else           (a[m]<t && t<=a[r])? l=m+1: r=m-1;//否則右半段有序;若t在(a[m],a[r]]收左,否丟到左半
        }
        return -1;
    }
};

中點二分。
1)步數是對數級。
2)判斷哪側有序,目標若在有序側就收縮到那側。
3)每輪區間嚴格變小,必收斂,不卡。

左半有序情況
陣列:[4,5,6,7,0,1,2],l=0,r=6 ⇒ m=(0+6)/2=3,a[m]=7
a[l]=4 ≤ a[m]=7,左半 [4,5,6,7] 有序。

t=5:落在 [a[l],a[m))=[4,7) ⇒ r=m−1=2(收右界)。
右邊界改成 m-1,丟掉「中點含右邊」那一半,只在左半段找。
例:l=0,r=6,m=3 → 設 r=m-1=2,區間變成 [0..2]。

t=0:不在該區間 ⇒ l=m+1=4(丟到右半段)。
1)「不在該區間」指:左半有序區間的值域是 [a[l], a[m])=[4,7)。因為 0 不落在 [4,7) 裡,所以判定「不在該區間」。
2)因此丟掉左半,把左邊界設為中點右一格:l=m+1=3+1=4。新搜尋區間變成索引 [4..6],數值是 [0,1,2]。

右半有序情況
同陣列,取 l=3,r=6 ⇒ 子陣列 [7,0,1,2],m=(3+6)/2=4,a[m]=0
因 a[l]=7 > a[m]=0,故右半 [0,1,2] 有序。

t=2:落在 (a[m],a[r]]=(0,2] ⇒ l=m+1=5(收左界,保留右半)。
t=7:不在該區間 ⇒ r=m−1=3(收右界,轉向左半)。


上一篇
Binary Search 2->3 & The Exit 8之餘第一個周末gogo 不容易耶XD
下一篇
Binary Search 4->5 & 平日颱風假上班有兩倍,去嗎
系列文
轉職仔之Data Science and ai master後的持續精進技術之路8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言