problem k: 查找某一个数_quot;细节魔鬼quot; 二分查找
二分查找,是一個高效,實用,且易理解的一個查找算法, 通常時間復雜度為O(lgn)。局限性在于,待查找對象必須為有序的數組;數據量過小,優勢不明顯,數據量過大,數組大小受限于內存。
除此之外,二分查找是面試中比較高頻考察的算法。
高頻題目清單:
二分查找應用(簡單)
- 374 猜數字大小
- 375 猜數字大小II
- 35 搜索插入位置
- 278 第一個錯誤的版本
- 367 有效的完全平方數
- 69 x的平方根
- 441 排列硬幣
二分查找應用(中等)
- 50 Pow(x,n)
- 29 兩數相除
- 34 在排序數組中查找元素的第一個和最后一個位置
- 540 有序數組中的單一元素
- 275 H指數II
- 436 尋找右區間
- 300 最長上升子序列
- 718 最長重復子數組
- 354 俄羅斯套娃信封問題
- 658 找到K個最接近的元素
- 162 尋找峰值
- 4 尋找兩個正序數組的中位數
- 209 長度最小的子數組
- 222 完全二叉樹的節點個數
- 287 尋找重復數
二分查找與旋轉數組
- 153 尋找旋轉排序數組中的最小值
- 154 尋找旋轉排序數組中的最小值II
- 33 搜索旋轉排序數組
- 81 搜素旋轉排序數組II
- 74 搜索二維矩陣
二分答案法
- 378 有序矩陣中第K小的元素
- 668 乘法表中第K小第數
- 410 分割數組的最大值
- 483 最小好進制
刷題技巧
關于二分查找,有個說法 “思路簡單,細節是魔鬼”,相關的刷題技巧和注意事項,網上大神們總結了很多,自己加工總結后的筆記:
1. 題目出現排序數組,優先思考是否可以用二分查找。
2. 找mid值,記住無腦寫 int mid = (left + right) >>> 1
當然 int mid = left + (right - left) / 2 ?或者 int mid = left + ((right - left) >> 1) 也是對的.
但是萬萬不能寫int mid = (left + right) / 2 ,原因是,如果left + right 有可能造成整型溢出,而left + (right - left),因為right和left一般是索引值,所以基本不會溢出。
至于推薦寫int mid = (left + right) >>> 1 ,除了裝逼外,還是jdk官方的標準寫法,也是因為位運算更快的原因。
3. int mid = (left + right) >>> 1,對于偶數數組長度來說,找的是左中點,int mid = (left + right + 1) >>> 1,找的是右中點。
找幾個case測試理解后,牢牢背住就行,不加一是左中點,加一是右中點。
4. 循環中的終止條件,寫while(left < right) 還是while (left <= right) ,大有乾坤。
left < right 和left <= right 區別在于,如果左右邊界一樣時,前者會漏掉一個數的查找。不過這也取決于最開始,right的值是否為nums.length -1。使用left < right的好處在,退出循環時,left一定等于right,不用額外考慮返回值。不過需要額外處理最后一個未查找的值。
這兩部篇文章分析了兩種條件的影響和處理調整:
https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-xiang-jie-by-labuladong/
https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/
這篇文章極力安利了第一種寫法:https://zhuanlan.zhihu.com/p/123863325
所有的文章,包括你我自己寫的,都只是個人的見解。
我認為必須了解兩種的寫法具體意義和影響,不同題目下才能具體情況具體處理。
高頻題目
704.二分查找
題目描述:
給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ?,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。
示例:
輸入: nums = [-1,0,3,5,9,12], target = 9
輸出: 4
解釋: 9 出現在 nums 中并且下標為 4
解題思路:
最最基礎的二分查找題目,考慮以上技巧,分別使用left < right 和left <= right 兩種循環條件寫出代碼,感受邊界處理。
????if?(nums?==?null?||?nums.length?<=?0)?{
????????return?-1;
????}
????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????//?左閉右閉區間,搜索不會漏掉值
????while?(left?<=?right)?{
????????mid?=?(right?+?left)?>>>?1;
????????if?(nums[mid]?==?target)?{
????????????return?mid;
????????}?else?if?(nums[mid]?>?target)?{
????????????//?因為循環條件中是右閉區間,
????????????//所以要跳過mid值,mid得-1
????????????right?=?mid?-?1;
????????}else?{
????????????left?=?mid?+?1;
????????}
????}
????return?-1;
}
2.left < right 左閉右開寫法
public?int?search2(int[]?nums,?int?target)?{????if?(nums?==?null?||?nums.length?<=?0)?{
????????return?-1;
????}
????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?????????mid?=?(right?+?left)?>>>?1;
????????if?(nums[mid]?==?target)?{
????????????return?mid;
????????}else?if?(nums[mid]?>?target)?{
????????//因為循環條件為右開區間
????????//所以跳過mid值,右區間應為mid
????????????right?=?mid;
????????}else?{
????????????left?=?left?+?1;
????????}
????}
????//?處理最后沒查找的元素,
????//最后一次left==right一定成立,
????//所以這塊left或者right都可以
????return?nums[left]?==?target???left?:?-1;
}
最后,附上,jdk中的寫法:
34.在排序數組中查找元素的第一個和最后一個位置
題目描述:
給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。
你的算法時間復雜度必須是 O(log n) 級別。
如果數組中不存在目標值,返回?[-1, -1]。
示例:
輸入: nums = [5,7,7,8,8,10], target = 8
輸出: [3,4]
解題思路:
先簡單二分查找到target值后,然后向前向后遍歷,找到第一個不重復的和最后一個不重復的值,這樣做的話,如果數組元素全是同一個target值,那么時間復雜度就是O(n)了,不符合題目要求了。
所以先解決 如何在O(log n)時間內找到元素第一次出現的位置 :
和基礎二分查找不同的是,在nums[mid] == target后,不能直接返回mid,而是應該讓縮小右邊界,繼續查找。在退出循環后,對整個數組沒有target值的情況做處理。
public?int?searchFirst(int[]?nums,?int?target)?{????if?(nums?==?null?||?nums.length?<=?0)?{
????????return?-1;
????}
????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?left?+?(right?-?left)?/?2;
????????//?當中點值和target相等時,更新右邊界
????????//?不和下面分支判斷合一塊,是為了邏輯清晰
????????if?(nums[mid]?==?target)?{
????????????right?=?mid?-?1;
????????}else?if?(nums[mid]?>?target)?{
????????????right?=?mid?-?1;
????????}else?{
????????????left?=?mid?+?1;
????????}
????}
????//?不用nums[right]?和target比較,
????//是因為在中點相等時,跳過了中點,
????//且right=mid-1。
????//?而left總和mid + 1。?
????//?所以用nums[left]和target比較。
????//?當最后一次查找,left?=?nums.length?-?1時,
????//?left有可能+1,等于nums.length
????// nums[left]就有可能下標越界。
????return?left?>=?nums.length?||?nums[left]?!=?target???-1?:?left;
}
查找目標元素的最后一次出現的位置:
同樣的,在中點值等于target時,不要返回mid,而是更新左邊界。記得最后在退出循環后,對整個數組沒有target值的情況做處理。
????if?(nums?==?null?||?nums.length?<=?0)?{
????????return?-1;
????}
????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?left?+?(right?-?left)?/?2;
????????if?(nums[mid]?==?target)?{
????????????left?=?mid?+?1;
????????}else?if?(nums[mid]?>?target)?{
????????????right?=?mid?-?1;
????????}else?{
????????????left?=?mid?+?1;
????????}
????}
????//?和找第一個元素位置一樣
????//?選nums[right]和target比較是因為:
????//?當中點和target相等時,跳過mid,left = mid + 1了。
????//?當數組只有一個元素時,right有可能-1,變成-1,造成數組下標越界。
????//?當然更好一點,直接?return?left?-?1;
????//?因為left初始值是0,如果數組不存在target元素,即返回-1.
????return?right?}
最后,解決這道題,只需:
public?int[]?searchRange(int[]?nums,?int?target)?{????//?這塊處理邊界條件后,剩下兩個函數可去掉。
????if?(nums?==?null?||?nums.length?<=?0)?{
????????return?new?int[]{-1,-1};
????}
????return?new?int[]?{searchFirst(nums,?target),?searchLast(nums,?target)};
}
367.有效的完全平方數
題目描述:
給定一個正整數 num,編寫一個函數,如果 num 是一個完全平方數,則返回 True,否則返回 False。
示例一:
輸入:16
輸出:true
示例二:
輸入:14
輸出: false
解題思路:
這是一道簡單題,我們每次取中點值,然后判斷中點值自乘是否等于num,如果等于,證明該num是完全平方數,否則更新左右指針。
注意學習點:
一個數的平方根最大不會超過它本身,再細點,基本不會超過它的一半。, ?解不等式,得到 或者。所以,當a =0,1,2,3時,它們的平方根是超過它們自身一半的,對應的平方根解分別是,0,1,1,1。所以,為了處理這4個特殊情況,初始值left = 0, right = x/2 + 1。
public?boolean?isPerfectSquare(int?num)?{????int?left?=?0,?right?=?num?/?2?+?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?(left?+?mid)?>>>?1;
????????if?(mid?*?mid?==?num)?{
????????????return?true;
????????}else?if?(mid?*?mid?>?num)?{
????????????right?=?mid?-?1;
????????}else?{
????????????left?=?mid?+?1;
????????}
????}
????return?false;
}
69.x的平方根-sqrt(x)
題目描述:
實現 int sqrt(int x)?函數。
計算并返回 x 的平方根,其中 x 是非負整數。
由于返回類型是整數,結果只保留整數的部分,小數部分將被舍去。
示例:輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842..., 由于返回類型是整數,小數部分將被舍去。
解題思路:
該題最快的解法并不是二分查找,有O(1)的袖珍計算器算法和同是O(lgn)卻更快的牛頓迭代法。
這兩種數學算法,具體思路參考官方題解:
https://leetcode-cn.com/problems/sqrtx/solution/x-de-ping-fang-gen-by-leetcode-solution/
二分查找的具體做法,和上題差不多,初始右邊界,選擇right = x/2 + 1。注意在退出循環后,如果使用while(left <= right),得考慮返回值如何選擇。
如case 8 的平方根是 2.82842...,應該返回2。left在非return正常退出循環時,可能會mid + 1,不合適,right退出循環時,是mid-1,符合題目取整數的要求。
????//?用long?防止int*int后溢出
????long?left?=?0,?right?=?x?/?2?+?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?(left?+?right)?>>>?1;
????????long?square?=?mid?*?mid;
????????if?(square?==?x)?{
????????????return?(int)mid;
????????}else?if?(square?>?x)?{
????????????right?=?mid?-?1;
????????}else??{
????????????left?=?mid?+?1;
????????}
????}
????//?按要求,比如8,平方根2.82842,所求解為2.
????//?對于left?<=?right,在正常退出時,left?=?right?+?1
????// right每次更新都是mid - 1,所以直接返回right即可,或者left - 1。
????return?(int)right;
}
50 Pow(x,n)
題目說明:
實現 pow(x, n) ,即計算 x 的 n 次冪函數。
示例1:
輸入: 2.00000, 10
輸出: 1024.00000
示例2:
輸入: 2.00000, -2
輸出: 0.25000
解釋: 2-2 = 1/22 = 1/4 = 0.25
說明:-100.0 < x < 100.0
n 是 32 位有符號整數,其數值范圍是 [?231, 231 ? 1]
解題思路:
最壞的解法,就是遍歷一遍,不斷相乘。二分法的思想在這題上,比如要算2的10次方,只要求得2的5次方即可;2的5次方只要求2的2次方,然后結果自乘即可. ?自然想到也要使用遞歸。
可以看到,需要注意的是,當n為奇數時,中間結果還需要再乘以當前數。除此之外,還應該考慮x為負數的情況,x為負數,所求結果要被1除,即倒數。
public?double?myPow(double?x,?int?n)?{????long?N?=?n;
????return?N?>=?0???quickMul(x,?N)?:?1.0?/?quickMul(x,?-N);
}
public?double?quickMul(double?x,?long?n)?{
????if?(n?==?0)?{
????????return?x;
????}
????double?y?=?quickMul(x,?n?/?2);
????return?n?%?2?==?0???y?*?y?:?y?*?y?*?x;
}
153.尋找旋轉排序數組中的最小值
題目描述:
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。
請找出其中最小的元素。你可以假設數組中不存在重復元素。
示例:
輸入: [4,5,6,7,0,1,2]
輸出: 0
解題思路
主要思路就是通過判斷中點值與邊值的大小來縮小查找的左右區間。
本題有3個關鍵點:
1好理解,使用left
2.3的考慮,二分查找題目分析一定要考慮數組只有兩個元素的case,就能確定到底使用左中點合適還是右中點合適。
此題,如果case為[1,3],如果選左中點,用左邊界比較,就會很麻煩:如果nums[mid] = num[left],left肯定不能mid+1跳過,但是如果left=mid,就死循環了。
如果選右中點,用左邊界比較,也會有問題,正常情況nums[mid] > num[left],肯定右半邊是較小的區間,left跳過mid,但是case[1,3]來說,跳過1就有問題。
所以,求旋轉數組最小值,因為旋轉點的右區間是小區間,所以用左中值和右邊值比較,當左中值和右值相等時,右邊值由可能是最小值,注意右邊值不能跳過mid。
public?int?findMin(int[]?nums)?{????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?????????mid?=?(left?+?right)?>>>?1;
????????if?(nums[mid]?>?nums[right])?{
????????????left?=?mid?+?1;
????????}else?{
????????????right?=?mid;
????????}
????}
????return?nums[mid];
}
154.尋找旋轉排序數組中的最小值II
題目描述:
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組?[0,1,2,4,5,6,7] 可能變為?[4,5,6,7,0,1,2]?)。
請找出其中最小的元素。
注意數組中可能存在重復的元素。
示例 1:
輸入: [3,3,1,3]
輸出: 1
示例 2:
輸入: [2,2,2,0,1]
輸出: 0
解題思路:
基于上題,如果沒有重復元素,如果左中點值和右值相等時nums[mid] = nums[right],右值有可能是小值,不能跳過,就更新右邊值right = mid。
如果有重復元素后,處理也簡單,當左中值和右值相等,讓右指針往左滑動,right = right - 1, 跳過迷惑值。
public?int?findMin(int[]?nums)?{????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?????????mid?=?(left?+?right)?>>>?1;
????????//?相等時,跳過右邊這個迷惑值
????????if?(nums[mid]?==?nums[right])?{
????????????right?=?right?-?1;
????????}
????????if?(nums[mid]?>?nums[right])?{
????????????left?=?mid?+?1;
????????}
????????if?(nums[mid]?????????????right?=?mid;
????????}
????}
????return?nums[left];
}
33 搜索旋轉排序數組
題目描述:
給你一個升序排列的整數數組 nums ,和一個整數 target 。
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。(例如,數組?[0,1,2,4,5,6,7]?可能變為?[4,5,6,7,0,1,2] )。
請你在數組中搜索 target ,如果數組中存在這個目標值,則返回它的索引,否則返回?-1 。
示例 1:
輸入:nums=[4,5,6,7,0,1,2], target = 0
輸出:4
解題思路:
和上面找最小值一樣,通過中值和邊值的比較,先確定有序的數組,然后通過判斷target是否在區間內,來更新左右邊值。
使用左中點的話,
- 如果nums[mid] >= nums[left], 可以證明[left,mid]左半段是有序的。當target在[left,mid)區間內,更新右邊值right = mid - 1,否則更新左邊值left = mid + 1。
?使用>=是因為是用的是左中點,得考慮只有兩個元素的case。 - nums[mid] < nums[left], 右半段[mid,right]是有序的
當target在(mid,right],更新左邊值left = mid + 1, 否則更新右邊值right = mid - 1
????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?(left?+?right)?>>>?1;
????????if?(nums[mid]?==?target)?{
????????????return?mid;
????????}
????????//?如果中點值大于左值,說明左半邊是有序的
????????if?(nums[mid]?>=?nums[left])?{
????????????//?如果目標值在左區間,更新右邊界
????????????if?(target?>=?nums[left]?&&?target?????????????????right?=?mid?-?1;
????????????}else?{
????????????????left?=?mid?+?1;
????????????}
????????}else?{
????????????//?右半邊是有序的,如果目標值在右半邊區間,更新左邊界????????????????????????????????????????????
????????????if?(target?>?nums[mid]?&&?target?<=?nums[right])?{
????????????????left?=?mid?+?1;
????????????}else?{
????????????????right?=?mid?-?1;
????????????}
????????}
????}
????return?-1;
}
81.搜索旋轉排序數組II
題目描述:
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
編寫一個函數來判斷給定的目標值是否存在于數組中。若存在返回 true,否則返回 false。
進階:
這是 搜索旋轉排序數組 的延伸題目,本題中的 nums 可能包含重復元素。這會影響到程序的時間復雜度嗎?會有怎樣的影響,為什么?
示例:
輸入:nums=[2,5,6,0,0,1,2], target = 0 輸出: true
解題思路:
和154.尋找旋轉排序數組中的最小值II題一樣,當nums[mid] == nums[left]時,需要滑動left邊值指針,跳過迷惑項。
如果這么處理,當待排序數組全是一樣的重復元素,時間復雜度會退化為O(n)。
????int?left?=?0,?right?=?nums.length?-?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?(left?+?right)?>>>?1;
????????if?(nums[mid]?==?target)?{
????????????return?true;
????????}
????????//?跳過迷惑值
????????if?(nums[mid]?==?nums[left])?{
????????????left?++;
????????}else?if?(nums[mid]?>?nums[left])?{
????????????if?(target?>=?nums[left]?&&?target?????????????????right?=?mid?-?1;
????????????}else?{
????????????????left?=?mid?+?1;
????????????}
????????}else?{
????????????if?(target?>?nums[mid]?&&?target?<=?nums[right])?{
????????????????left?=?mid?+?1;
????????????}else?{
????????????????right?=?mid?-?1;
????????????}
????????}
????}
????return?false;
}
74.搜索二維矩陣
題目描述:
編寫一個高效的算法來判斷 m x n 矩陣中,是否存在一個目標值。該矩陣具有如下特性:
每行中的整數從左到右按升序排列。
每行的第一個整數大于前一行的最后一個整數。
示例:
輸入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,50]], target = 3
輸出:true
解題思路:
從示例上就能看到,講該二維矩陣按行依次展開,就是一個升序的一維數組。
然后就能按標準的二分查找來做題了。
此題關鍵技巧,如果展開后的一維數組的下班為i。
和m(row length) * n(col length)二維數組存在以下關系:
- row = i / n
- col = i % n
????if?(matrix?==?null?||?matrix.length?<=?0)?{
????????return?false;
????}
????int?m?=?matrix.length;
????int?n?=?matrix[0].length;
????if?(n?<=?0)?{
????????return?false;
????}
????int?left?=?0,?right?=?m?*?n?-?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?(left?+?right)?>>>?1;
????????int?val?=?matrix[mid?/?n][mid?%?n];
????????if?(val?==?target)?{
????????????return?true;
????????}else?if?(val?>?target)?{
????????????right?=?mid?-?1;
????????}else?{
????????????left?=?mid?+?1;
????????}
????}
????return?false;
}
240.搜素二維矩陣II
題目描述:
編寫一個高效的算法來搜索 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性:
每行的元素從左到右升序排列。
每列的元素從上到下升序排列。?
示例:
現有矩陣 matrix 如下:
[1, ? 4, ?7, 11, 15],
[2, ? 5, ?8, 12, 19],
[3, ? 6, ?9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
給定 target = 5,返回 true。
給定 target = 20,返回 false。
解題思路:
和上題不一樣的是,下一行的起始值不一定會比上一行末尾值大。但是每一行和每一列是各自升序的。所以,對于m*n的矩陣,遍歷i次,i取m和n的最小值,分別在第i列和第i行進行二分查找。
時間復雜度分析:
循環次數i = min(m,n), 每次循環分別二分查找列和行,時間復雜度O(lg(m-i)) + O(lg(n-i))。近似O(2*lg(n-i)) = O(lg(n))。最壞當m==n時,總的運行時間: O(lg(n) + lg(n-1) + lg(n-2) + ... + lg(1)) = O(lg(n*(n-1)*(n-2)*...*1)) = O(lg(n!))
????if?(matrix?==?null?||?matrix.length?<=?0)?{
????????return?false;
????}
????int?count?=?Math.min(matrix.length,?matrix[0].length);
????for?(int?i?=?0;?i?????????boolean?rowSearchRes?=?bSearch(matrix,?target,?i,?true);
????????if?(rowSearchRes)?{
????????????return?true;
????????}
????????boolean?colSearchRes?=?bSearch(matrix,?target,?i,?false);
????????if?(colSearchRes)?{
????????????return?true;
????????}
????}
????return?false;
}
private?boolean?bSearch(int[][]?martix,?int?target,?int?i,?boolean?searchRow)?{
????int?left?=?i,?right?=?searchRow???martix[0].length?-?1?:?martix.length?-?1,?mid?=?0;
????while?(left?<=?right)?{
????????mid?=?(left?+?right)?>>>?1;
????????if?(searchRow)?{
????????????if?(target?==?martix[i][mid])?{
????????????????return?true;
????????????}
????????????if?(target?>?martix[i][mid])?{
????????????????left?=?mid?+?1;
????????????}
????????????if?(target?????????????????right?=?mid?-?1;
????????????}
????????}else?{
????????????if?(target?==?martix[mid][i])?{
????????????????return?true;
????????????}
????????????if?(target?>?martix[mid][i])?{
????????????????left?=?mid?+?1;
????????????}
????????????if?(target?????????????????right?=?mid?-?1;
????????????}
????????}
????}
????return?false;
}
按照本題二維矩陣的特性,如果把左下角的值當做根節點,可以將矩陣看做一個二叉搜索樹,上一個列值比它小,下一個行值比它大。
所以,從最下角值開始搜索,如果目標值大于當前值,后面的所有的行值也都是大于目標值的,列往上移動。
如果目標值小于當前值,往上的所有列值都是小于目標值的,移動下一行。
時間復雜度O(m+n),空間復雜度O(1)。
public?boolean?searchMatrix(int[][]?martrix,?int?target)?{????if?(martrix?==?null?||?martrix.length?<=?0)?{
????????return?false;
????}
????int?row?=?martrix.length?-?1,?col?=?0;
????while?(col?=?0)?{
????????if?(martrix[row][col]?==?target)?{
????????????return?true;
????????}?else?if?(martrix[row][col]?>?target)?{
????????????row?=?row?-?1;
????????}else?{
????????????col?=?col?+?1;
????????}
????}
????return?false;
}
總結
二分查找題目注意在使用不同while條件時,不同的細節處理,包括左右指針的更新,退出循環后的取值考慮。
記得不要忘記分析只有兩個元素的case。
旋轉數組類的查找,首先要通過中值與邊值的比較,來確定哪半邊是有序的。升序數組旋轉后右半邊是小區間,求旋轉數組最小值時,使用左中值和右邊值比較。
查找數組中,如果有重復元素,需要滑動指針,跳過疑惑值,但是有可能時間復雜度退化為O(n)。
總結
以上是生活随笔為你收集整理的problem k: 查找某一个数_quot;细节魔鬼quot; 二分查找的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python numpy库安装 mac_
- 下一篇: python合法标识符_python_判