二分查詢
又稱折半查詢,
對排好序的陣列,每次取這個數和陣列中間的數進行比較,複雜度是
o(logn)如:
設陣列為
a[n],查詢的數x,
如果x==a[n/2]
,則返回
n/2; 如果
x < a[n/2],則在
a[0]
到a[n/2-1]
中進行查詢;
如果x > a[n/2]
,則在a[n/2+1]
到a[n-1]
中進行查詢; 優點
是比較次數少,查詢速度快,平均效能好;其
缺點是要求待查表為有序表,且插入刪除困難。
條件:查詢的陣列必須要為有序陣列。
[cpp]
view plain
copy
/*歸的二分查詢
arrat:陣列 , low:上界; high:下界; target:查詢的資料; 返回target所在陣列的下標
*/int
binarysearch(
intarray,
intlow,
inthigh,
inttarget)
if(target == array[middle])
if(target < array[middle])
if(target > array[middle])
}
[cpp]
view plain
copy
/*非遞迴的二分查詢
arrat:陣列 , n:陣列的大小; target:查詢的資料; 返回target所在陣列的下標
*/int
binarysearch2(
intarray,
intn,
inttarget) else
if(target < array[middle]) else
if(target > array[middle])
} return
-1;
}
推薦使用非遞迴的方式,因為遞迴每次呼叫遞迴時有用堆疊儲存函式資料和結果。
能用迴圈的盡量不用遞迴。
c++如何跳出多層迴圈
》中提到的抽籤問題進行分析。 4
),資料大時其計算量會大的驚人。為便於分析,將之前**帖至如下:
[cpp]
view plain
copy
**
抽籤問題
解決方案,複雜度n^4
*/
void
drawlots()
bool
result =
false
; bool
isbreakloop =
true
; int
_sum = 0;
for(
inta = 0; a < numofcard && isbreakloop; a ++)
} }
} }
cout << "_sum:"
<< _sum <<
" "
<<
"sum:"
<< sum << endl;
if(result) else
cout<<"no"
<
}
最內層迴圈所做事如下: k
a + k
b+ k
c+ k
d= m
移項後如下: k
d= m - (k
a + k
b+ kc)
到第四層迴圈時,其實k
a ,kb,k
c已經知道,那問題也就變成了對k
d的查詢,我們可用上面講的二分查詢,複雜度就降為o(n
3logn).實現如下:
[cpp]
view plain
copy
/**抽籤問題
解決方案,複雜度n^3 * log(n)
*/void
drawlots2()
//對陣列進行排序
sort(k, k + numofcard);
intindex = -1;
bool
isbreakloop =
true
; for
(int
a = 0; a < numofcard && isbreakloop; a ++)
} }
} if
(index >= 0) else
cout<<"no"
<
}
根據上一步的優化方式,我們可以進一步對內側兩層迴圈(
也就是第三層和第四層
)進行思考: k
c+ k
d= m - (ka
+ kb)
我們不能直接對kc
+ kd
進行查詢,但是可以預先列舉出ka
+ kb的n2
種數值並排序,再對kc
+ kd
進行十分查詢。列出列舉o(n
2),排序
o(n2
logn), 迴圈
o(n2
logn),所以總的複雜度降為
o(n2logn)
,實現如下:
[cpp]
view plain
copy
/**抽籤問題
解決方案,複雜度n^2 * log(n)
*/void
drawlots3()
intcdnum = numofcard*(numofcard+1)/2;
intcdsum[cdnum];
inti = 0;
for(
inta=0; a
for(
intb=i; b
cdsum[i ++] = k[a] + k[b];
} }
//對陣列進行排序
sort(cdsum, cdsum + cdnum);
intindex = -1;
bool
isbreakloop =
true
; for
(int
a = 0; a < numofcard && isbreakloop; a ++)
} }
} if
(index >= 0) else
cout<<"no"
<
}
上面列舉ka
+ kb
時其實是有重複的,因為k[i] + k[j] == k[j] + k[i]
,去除重複值之後,ka
+ kb
值的個數是n(n+1)/2
。至於n(n+1)/2
怎麼來,可以簡單推導如下:
n m
1 1
2 2+1
3 3+2+1
4 4+ 3+2+1
......
實現如下:
[cpp]
view plain
copy
/**抽籤問題
解決方案,複雜度n^2 * log(n)
*/void
drawlots3_1()
intcdnum = numofcard*numofcard;
intcdsum[cdnum];
for(
inta=0; a
for(
intb=0; b
cdsum[a*numofcard + b] = k[a] + k[b];
} }
//對陣列進行排序
sort(cdsum, cdsum + cdnum);
intindex = -1;
bool
isbreakloop =
true
; for
(int
a = 0; a < numofcard && isbreakloop; a ++)
} }
} if
(index >= 0) else
cout<<"no"
<
}
python二分查詢基礎 005 入門
1.問題描述 給定乙個排序的整數組 公升序 和乙個要查詢的目標整數target,查詢到target第1次出現的下標 從0開始 如果target不存在於陣列中,返回 1 2.問題示例 輸入陣列 1,4,5,5,7,7,8,9,10 和目標整數1.輸出其所在的位置為0,即第1次出現在第0個位置。輸入陣列...
二分入門題
在乙個遞增的序列裡,查詢元素是否存在,若存在輸出yes,不存在輸出no.本題多組資料,首先輸入乙個數字n,然後輸入n個數,資料保證數列遞增,然後再輸入乙個查詢數字。若存在輸出yes,不存在輸出no.4 1 3 5 8 3 yes include include includeusing namesp...
二分簡單入門
參考文章 二分.1.最大化最小值 相當於n個東西分給m個人,使得每個人 至少拿x個 那麼每個人拿夠了 就走,給後面的人多留一點,只要能分夠 m個人 就是true,多的全 扔給最後乙個人就是了.2.最小化最大值 相當於n個東西分給m個人,每個人 至多能拿x個 那麼每個人盡可能 多拿一點,給後面的人少留...