版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
二分查找問(wèn)題全集1,原始二分查找題目:給定一個(gè)有序(非降序)數(shù)組A,求任意一個(gè)i使得A[i]等于target,不存在則返回-1例如:[2,4,6,8,9]找(4)位置11.1遞歸版[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
bSearch(int
a[],
int
low,
int
high,
int
target){
if(low
>
high)
return
-1;
int
mid
=
(low
+
high)/2;
if(target<a[mid])
return
bSearch(a,low,mid-1,target);
else
if(target>a[mid])
return
bSearch(a,mid+1,high,target);
//if(target
==
a[mid])
return
mid;
}
1.2迭代版[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
search(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
//
注意:若使用(low+high)/2求中間位置容易溢出
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
return
mid;
else
if(A[mid]
<
target)
low
=
mid+1;
else
//
A[mid]
>
target
high
=
mid-1;
}
return
-1;
}
1.3返回插入位置給定一個(gè)有序(非降序)數(shù)組A,若target在數(shù)組中出現(xiàn),返回位置,若不存在,返回它應(yīng)該插入的位置。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
search(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
//
注意:若使用(low+high)/2求中間位置容易溢出
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
return
mid;
else
if(A[mid]
<
target)
low
=
mid+1;
else
//
A[mid]
>
target
high
=
mid-1;
}
return
-(low+1);
}
之所以返回-(low+1)而不是直接返回-low是因?yàn)閘ow可能為0,如果直接返回-low就無(wú)法判斷是正常返回位置0還是查找不成功返回的0。2,含重復(fù)元素,求=target的最小一個(gè)問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A,可含有重復(fù)元素,求最小的i使得A[i]等于target,不存在則返回-1例如:A[2,4,6,8,8,8,9]求8得最小位置3[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
search(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
//
注意:若使用(low+high)/2求中間位置容易溢出
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
{
if(mid
>
0
&&
A[mid-1]
==
target)
high
=
mid-1;
else
return
mid;
}
else
if(A[mid]
<
target)
low
=
mid+1;
else
//
A[mid]
>
target
high
=
mid-1;
}
return
-(low+1);
}
3,含重復(fù)元素,求=target的最大一個(gè)問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A,可含有重復(fù)元素,求最大的i使得A[i]等于target,不存在則返回-1例如:A[2,4,6,8,8,8,9]求8得最大位置5[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
search(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
//
注意:若使用(low+high)/2求中間位置容易溢出
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
{
if(mid
<
n-1
&&
A[mid+1]
==
target)
low
=
mid+1;
else
return
mid;
}
else
if(A[mid]
<
target)
low
=
mid+1;
else
//
A[mid]
>
target
high
=
mid-1;
}
return
-(low+1);
}
4,含重復(fù)元素,求<target的最大一個(gè)問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A,可含有重復(fù)元素,求最大的i使得A[i]小于target,不存在則返回-1
例如:A[2,4,6,8,8,8,9]求9得最大位置5問(wèn)題轉(zhuǎn)化:含重復(fù)元素,求2【=target的最小一個(gè)】的前一個(gè)。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
search(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
//
注意:若使用(low+high)/2求中間位置容易溢出
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
{
if(mid
>
0
&&
A[mid-1]
==
target)
high
=
mid-1;
else
return
(mid==0)?-1:mid-1;
}
else
if(A[mid]
<
target)
low
=
mid+1;
else
//
A[mid]
>
target
high
=
mid-1;
}
return
-(low+1);
}
5,含重復(fù)元素,求>target的最小一個(gè)問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A,可含有重復(fù)元素,求最小的i使得A[i]大于target,不存在則返回-1例如:A[2,4,6,8,8,8,9]求6的最小位置3問(wèn)題轉(zhuǎn)化:含重復(fù)元素,求3【=target的最大一個(gè)】的后一個(gè)。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
search(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
//
注意:若使用(low+high)/2求中間位置容易溢出
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
{
if(mid
<
n-1
&&
A[mid+1]
==
target)
low
=
mid+1;
else
return
(mid==n-1)?-n:mid+1;
}
else
if(A[mid]
<
target)
low
=
mid+1;
else
//
A[mid]
>
target
high
=
mid-1;
}
return
-(low+1);
}
6,含重復(fù)元素,求=target的出現(xiàn)次數(shù)問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A,可含有重復(fù)元素,求target在數(shù)組中出現(xiàn)的次數(shù)。例如:A[2,4,6,8,8,8,9]求8的出現(xiàn)次數(shù)3求出第一次出現(xiàn)位置和最后一次出現(xiàn)位置。由于前面都已實(shí)現(xiàn),這里不多解釋。請(qǐng)參考實(shí)現(xiàn)代碼與注釋[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
count(int
A[],
int
n,
int
target)
{
int
firstPos
=
searchFirstPos(A,
n,
target);
//
第一次出現(xiàn)位置
if(firstPos
==
-1)
return
0;
int
lastPos
=
searchLastPos(A,
n,
target);
//
最后一次出現(xiàn)位置
return
lastPos-firstPos+1;
//
出現(xiàn)次數(shù)
}
7,含重復(fù)元素,求絕對(duì)值最小的元素問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A,可含有重復(fù)元素,求絕對(duì)值最小的元素的位置例如:A[-4,-2,-1,2,3,8,9]求結(jié)果為2[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
searchMinAbs(int
A[],
int
n)
{
int
low
=
0,
high
=
n-1;
while(low
<
high)
{
int
mid
=
low+((high-low)>>1);
if(A[mid]
<
0)
low
=
mid+1;
else
//
A[mid]
>=
0
high
=
mid;
}
/*
循環(huán)結(jié)束時(shí),如果low
!=
n-1,A[low]
>=
0,如果low>0,A[low-1]
<
0
*/
if(low
>
0
&&
abs(A[low-1])
<
abs(A[low]))
return
low-1;
else
return
low;
}
8,問(wèn)題:給定一個(gè)有序(非降序)數(shù)組A和一個(gè)有序(非降序)數(shù)組B,可含有重復(fù)元素,求兩個(gè)數(shù)組合并結(jié)果中的第k(k>=0)個(gè)數(shù)字。
這個(gè)題目出現(xiàn)了兩個(gè)數(shù)組,有序的,不管怎樣我們就應(yīng)該首先考慮二分查找是否可行。若使用順序查找,時(shí)間復(fù)雜度最低為O(k),就是類(lèi)似歸并排序中的歸并過(guò)程。使用用二分查找時(shí)間復(fù)雜度為O(logM+logN)。二分查找的具體實(shí)現(xiàn)過(guò)程請(qǐng)參考實(shí)現(xiàn)代碼與注釋。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
findKthIn2SortedArrays(int
A[],
int
m,
int
B[],
int
n,
int
k)
{
if(m
<=
0)
//
數(shù)組A中沒(méi)有元素,直接在B中找第k個(gè)元素
return
B[k];
if(n
<=
0)
//
數(shù)組B中沒(méi)有元素,直接在A中找第k個(gè)元素
return
A[k];
int
i
=
(m-1)>>1;
//
數(shù)組A的中間位置
int
j
=
(n-1)>>1;
//
數(shù)組B的中間位置
if(A[i]
<=
B[j])
//
數(shù)組A的中間元素小于等于數(shù)組B的中間元素
{
/*
設(shè)x為數(shù)組A和數(shù)組B中小于B[j]的元素?cái)?shù)目,則i+1+j+1小于等于x,
因?yàn)锳[i+1]到A[m-1]中還可能存在小于等于B[j]的元素;
如果k小于i+1+j+1,那么要查找的第k個(gè)元素肯定小于等于B[j],
因?yàn)閤大于等于i+1+j+1;既然第k個(gè)元素小于等于B[j],那么只
需要在A[0]~A[m-1]和B[0]~B[j]中查找第k個(gè)元素即可,遞歸調(diào)用下去。
*/
if(k
<
i+1+j+1)
{
if(j
>
0)
return
findKthIn2SortedArrays(A,
m,
B,
j+1,
k);
else
//
j
==
0時(shí)特殊處理,防止死循環(huán)
{
if(k
==
0)
return
min(A[0],
B[0]);
if(k
==
m)
return
max(A[m-1],
B[0]);
return
A[k]
<
B[0]
?
A[k]
:
max(A[k-1],
B[0]);
}
}
/*
設(shè)y為數(shù)組A和數(shù)組B中小于于等于A[i]的元素?cái)?shù)目,則i+1+j+1大于等于y;
如果k大于等于i+1+j+1,那么要查找到第k個(gè)元素肯定大于A[i],因?yàn)?/p>
i+1+j+1大于等于y;既然第k個(gè)元素大于A[i],那么只需要在A[i+1]~A[m-1]
和B[0]~B[n-1]中查找第k-i-1個(gè)元素,遞歸調(diào)用下去。
*/
else
return
findKthIn2SortedArrays(A+i+1,
m-i-1,
B,
n,
k-i-1);
}
//
如果數(shù)組A的中間元素大于數(shù)組B的中間元素,那么交換數(shù)組A和B,重新調(diào)用即可
else
return
findKthIn2SortedArrays(B,
n,
A,
m,
k);
}
9問(wèn)題:
一個(gè)有序(升序)數(shù)組,沒(méi)有重復(fù)元素,在某一個(gè)位置發(fā)生了旋轉(zhuǎn)后,求target在變化后的數(shù)組中出現(xiàn)的位置,不存在則返回-1如0124567可能變成4567012
我們先比較中間元素是否是目標(biāo)值,如果是返回位置。如果不是,我們就應(yīng)該想辦法將搜索區(qū)間減少一半。因?yàn)榇嬖谛D(zhuǎn)變化,所以我們要多做一些判斷。我們知道因?yàn)橹挥幸淮涡D(zhuǎn)變化,所以中間元素兩邊的子數(shù)組肯定有一個(gè)是有序的,那么我們可以判斷target是不是在這個(gè)有序的子數(shù)組中,從而決定是搜索這個(gè)子數(shù)組還是搜索另一個(gè)子數(shù)組。具體請(qǐng)參考實(shí)現(xiàn)代碼與注釋。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
searchInRotatedArray(int
A[],
int
n,
int
target)
{
int
low
=
0,
high
=
n-1;
while(low
<=
high)
{
int
mid
=
low+((high-low)>>1);
if(A[mid]
==
target)
return
mid;
if(A[mid]
>=
A[low])
{
//
low
~
mid
是升序的
if(target
>=
A[low]
&&
target
<
A[mid])
high
=
mid-1;
else
low
=
mid+1;
}
else
{
//
mid
~
high
是升序的
if(target
>
A[mid]
&&
target
<=
A[high])
low
=
mid+1;
else
high
=
mid-1;
}
}
return
-1;
}
如果這樣的數(shù)組中存在重復(fù)元素,還能使用二分嗎?答案是不能。請(qǐng)看幾個(gè)例子
[1,2,2,2,2],[2,1,2,2,2],[2,2,1,2,2],[2,2,2,1,2],[2,2,2,2,1]這些都是有第一個(gè)數(shù)組旋轉(zhuǎn)一次變化來(lái)的,我們不能通過(guò)二分確定是否存在元素1.10,問(wèn)題:一個(gè)有序(升序)數(shù)組,沒(méi)有重復(fù)元素,在某一個(gè)位置發(fā)生了旋轉(zhuǎn)后,求最小值所在位置如果中間元素小于左端元素,則最小值在左半?yún)^(qū)間內(nèi)(包含中間元素);如果中間元素大于右端元素,則最小值在右半?yún)^(qū)間內(nèi)(包含中間元素)。請(qǐng)參考實(shí)現(xiàn)代碼與注釋。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
searchMinInRotatedArray(int
A[],
int
n)
{
if(n
==
1)
return
0;
int
low
=
0,
high
=
n-1;
while(low
<
high-1)
//
保證mid
!=
low且mid
!=
high
{
int
mid
=
low+((high-low)>>1);
if(A[mid]
<
A[low])
//
最小值在low~mid
high
=
mid;
else
//
A[mid]
>
A[low],
//
最小值在mid和high之間
low
=
mid;
}
return
A[low]
<
A[low+1]
?
low
:
low+1;
}
11,問(wèn)題:
一個(gè)有序(升序)數(shù)組,沒(méi)有重復(fù)元素,在某一個(gè)位置發(fā)生了旋轉(zhuǎn)后,求第k(k>0)小元素的位置
我們可以利用上一題的解答,求出最小值所在位置后,便可以求出第k小元素。請(qǐng)參考實(shí)現(xiàn)代碼與注釋[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
searchKthInRotatedArray(int
A[],
int
n,
int
k)
{
int
posMin
=
searchMinInRotatedArray(A,
n);
return
(posMin+k-1)%n;
}
12,查找旋轉(zhuǎn)數(shù)組的最小數(shù)字題目:即找分界點(diǎn),比如34512,返回的是位置3。以題目中的旋轉(zhuǎn)數(shù)組為例,{3,4,5,1,2},我們可以有序數(shù)組經(jīng)過(guò)旋轉(zhuǎn)以后被分割為兩段有序的數(shù)組,比如此處被分為{3,4,5}{1,2}這樣連個(gè)數(shù)組,并且前半段數(shù)組中的數(shù)字肯定大于等于后半段的數(shù)組。我們找中間元素a[mid],讓其跟元素首元素a[low]和尾元素a[high]比較,如果大于首元素a[low],則中間元素屬于前半段有序數(shù)組;如果小于尾元素a[high],那么中間元素就是后半段的元素。這里我們?cè)O(shè)定兩個(gè)指針start和end分別指向數(shù)組的首尾元素,然后當(dāng)start指向前半段最后一個(gè)元素,end指向后半段第一個(gè)元素,這是程序就找到了數(shù)組中的最小元素,就是end指向的那個(gè)數(shù),程序的出口就是end-start==1。[cpp]\o"viewplain"viewplain\o"copy"copy\o"print"print\o"?"?int
bSearchMinValue(int
a[],
int
low,
int
high){
//終止遞歸條件是low和high差1,原因是后面mid都不是+1-1處理的
if(low+1==high)
return
high;
int
mid
=
(low
+
high)/2;
if(a[mid]>a[low])//左側(cè)有序,在右邊找分界點(diǎn)
return
bSearchMinValue(a,mid,high);
if(a[mid]<a[high])//右側(cè)有序,在左邊找分界點(diǎn)
return
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 告別沈從文課件
- 少兒街舞 課件
- 籃球課件 英語(yǔ)
- 第二講 寫(xiě)寫(xiě)身邊的人(看圖寫(xiě)話(huà)教學(xué))-二年級(jí)語(yǔ)文上冊(cè)(統(tǒng)編版)
- 勝似親人 課件
- 西京學(xué)院《影視美學(xué)》2021-2022學(xué)年第一學(xué)期期末試卷
- 關(guān)于情緒 課件
- 三角形的高 (微課課件)
- 西京學(xué)院《紀(jì)錄片創(chuàng)作》2022-2023學(xué)年第一學(xué)期期末試卷
- 西京學(xué)院《采訪(fǎng)與寫(xiě)作》2021-2022學(xué)年第一學(xué)期期末試卷
- 心理疾病中醫(yī)常用治療方法
- 最全給排水基礎(chǔ)知識(shí)與識(shí)圖
- 《秘密》讀書(shū)分享課件
- 學(xué)做小小理財(cái)師
- 流感診療指南
- 《民航危險(xiǎn)品運(yùn)輸》教學(xué)課件 第一章 民航危險(xiǎn)品運(yùn)輸概述
- 寶寶白細(xì)胞高怎么回事:新生兒含有白細(xì)胞
- 《義務(wù)教育集團(tuán)化辦學(xué)考核評(píng)價(jià)辦法》
- 高中音樂(lè)《學(xué)會(huì)聆聽(tīng)音樂(lè)》第三課時(shí)《聯(lián)想與想象》 課件
- 崗位技能矩陣圖
- 腳手架的拆除安全檢查表
評(píng)論
0/150
提交評(píng)論