2019 08 08 二分思想

2021-09-25 23:48:21 字數 1640 閱讀 6762

今天做了一道二分題

感覺二分仍需要加強

乙個經典題目

求乙個遞增陣列裡某個數字出現次數

我們第一想法:暴力

的確可以

邊讀入邊判斷是否為我們要的那個數

這種複雜度是o(n)

有沒有更高效演算法呢?

二分!!!

我們可以二分查詢陣列中這個數出現的第乙個位置和最後乙個位置

數量不就得出來了嗎

那麼怎麼二分呢?

我們知道二分的形式無非就是

while

(lelse

}

那麼其中要不要加+1還是-1,什麼時候加呢?

我們還沒有乙個固定思路

可以先假設兩個相鄰相同元素

…… 2 2 ……

如果我們要找出現2的第乙個位置

那麼我們的a[mid]==2

我們應該修改l還是r呢?

答案當然是r

因為我們不敢修改l,一修改就可能把第乙個位置跳過了

那麼r變成啥呢?

r=mid-1 嗎?還是直接r=mid?

這裡我們選擇r=mid

因為mid可能就在第乙個數字的位置,我們不能跳過

接下來考慮是(l+r+1)>>1還是(l+r)>>1呢?

我們上面的兩個相鄰相同元素就可以用上了

如果是選用前者,那麼如果中間有兩個數,會選擇右邊的數

而我們想揪出第乙個數

得選左邊的數叭

所以我們選擇了(l+r)>>1

接下來想想如果a[mid]我們在這種情況下不能修改r,只能修改l=mid(+1)

是否要+1呢?

要!!!

因為mid位置絕對不可能是第乙個位置

所以直接可以跳過

於是乎,剩下最後的a[mid]>k時

顯然同a[mid]==k的情況

**如下

for

(l=0

,r=n;l)else

}

為啥邊界是左閉右開呢(所謂邊界就是l和r的初值,我這裡寫的是0和n,下標n是不會存在於陣列裡的)

因為我們的右邊界一定要更新!

最後的結果是看r

我也不太確定,這裡的結果用l和r都是一樣的叭

然後要取最後乙個數的話,同理

所有**如下

#include.h>

using namespace std;

int a[

10000007];

inline int

read()

while

(ch>=

'0'&&ch<=

'9')

return x;

}int

main()

}int pre,last,l,r;

for(l=

0,r=n;l)else

} pre=r;

for(l=-1

,r=n-

1;l)else

} last=l;

printf

("%d"

,last-pre+1)

;return0;

}

很多時候也會用

r+(r-l)/2防止溢位

二分查詢思想

二分查詢思想應用於對有序的陣列進行查詢操作。時間複雜度 二分查詢也稱為折半查詢,每次都能將查詢區間減半,這種折半特性演算法時間複雜度為o logn mid計算 有兩種計算中值mid的方式 l h可能出現加法溢位,也就是說加法的結果大於整形能夠表示的範圍。但是l和h都為正數,因此h l不會出現加法溢位...

二分思想小剖析

這乙個月努力沖一沖,三月份的甲級能考掉就考掉了。今天看演算法筆記看到了二分,想著二分還不簡單。看了看發現並不是?演算法筆記中有一句加粗的話是我以前在二分中從沒聽過的,大部分二分問題可以歸結為 尋找有序序列中第乙個滿足某條件的元素的位置。這句話一開始聽得不明所以,仔細一想別有洞天。比如下面的木棒切割問...

二分查詢的思想

先看看leetcode兩道相關的題目,都是二分思想的應用。leetcode 35 leetcode 34 二分思想用一句話概況就是 一看就懂,一寫就廢 花了很長時間都沒有弄得懂,每個人都是不同的寫法,新手很難從中發現規律。其實二分查詢最重要的一句話就是 查詢範圍 如何確定查詢範圍?只要確定了查詢範圍...