給定乙個排序陣列和乙個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。
你可以假設陣列中無重複元素。
示例 1:
輸入: [1,3,5,6], 5
輸出: 2
示例 2:
輸入: [1,3,5,6], 2
輸出: 1
示例 3:
輸入: [1,3,5,6], 7
輸出: 4
示例 4:
輸入: [1,3,5,6], 0
輸出: 0
按照二分法思路列舉示例歸納規律:[1,3,5,6]
begin = 0, end = 3, mid = 1; target = 5, 恰好是nums[mid].
target = 2, target < nums[mid] && target > nums[mid-1], 所以 返回 mid -1;
同樣地,當 target > nums[mid] && target < nums[mid+1], 返回 mid + 1;
target = 7, target > nums[mid], begin = mid + 1 = 2; mid = (2 + 3)/2 = 2;
target > nums[mid]; begin = mid + 1 = 2 + 1 = 3, mid = (3 + 3)/2 = 3;
target > nums[mid]; begin = mid + 1 = 4, 出現了越界情況, 此時應該返回mid+1。應該邊界 mid = nums.size()-1 返回mid + 1;
同樣地,對於左邊界越界時,當mid = 0時,返回0;
class
solution
end = mid -1;
}else
if(target > nums[mid]
) begin = mid +1;
}}return index;}}
;
小節:二分查詢的實質就是不斷更新mid,然後來鎖定要找的target,本題同樣也是這樣,不過不同的是本題還需要對mid周圍的值施加限制:target只能是出現在mid的左/右兩邊,或者是出現在左右邊界。
這個對mid周圍值施加限制條件的思想,還會在下一題中應用的到。
給定乙個按照公升序排列的整數陣列 nums,和乙個目標值 target。找出給定目標值在陣列中的開始位置和結束位置。
你的演算法時間複雜度必須是 o(l
ogn)
o(log n)
o(logn
) 級別。
如果陣列中不存在目標值,返回 [-1, -1]。
示例 1:
輸入: nums = [5,7,7,8,8,10], target = 8
輸出: [3,4]
示例 2:
輸入: nums = [5,7,7,8,8,10], target = 6
輸出: [-1,-1]
分析:
這個光靠舉例子是歸納規律還是有點難度的,需要分析一下;
如果光靠二分法能不能找到左右端點?顯然不能,二分查詢最短只能找到乙個目標值的位置或者確認這個值不存在。
既然二分法可以找到乙個目標值的位置,那麼也就能找到兩個端點,因為端點也是目標值。
從上面一題可以得知,二分查詢法就是不斷更新mid的值,從nums[mid]或者mid周圍的值來搜尋目標值的。
從[5,7,7,8,8,8,10]出發,如果mid指向最終間的那個8,即有 nums[mid] == target;由4可知,我們需要更新mid來查詢端點,要麼向左,要麼向右去更新mid,又因為一次查詢只能往乙個方向移動,但是左右端點位於兩個方向上,因此,需要對將左右兩個端點的查詢任務分開進行3
。查詢左端點:會有兩個情況:[5,7,7,8,8,8,10] 和 [8,8,8,10], 當 nums[mid] == target 時, 如果mid == 0 || target > nums[mid-1], 說明此時的mid是左端點,否則說明左端點在mid左面,即要將mid向左移動,又因為mid是通過begin和end更新的,所以令end = mid - 1來更新mid;剩餘的target < nums[mid]和 target > nums[mid] 情況和二分查詢法相同3
。查詢右端點:同樣會有兩個情況:[5,7,7,8,8,8,10] 和 [7,8,8,8], 當 nums[mid] == target 時, 如果mid == nums.size()-1 || target < nums[mid+1], 說明此時的mid是右端點,否則說明右端點在mid右面,即要將mid向右移動,又因為mid是通過begin和end更新的,所以令 begin = mid + 1;剩餘的target < nums[mid]和 target > nums[mid] 情況和二分查詢法相同3
。
class
solution
intleft_bound
(vector<
int>
& nums,
int target)
end = mid -1;
}else
if(target < nums[mid]
)else
if(target > nums[mid])}
return-1
;}intright_bound
(vector<
int>
& nums,
int target)
begin = mid +1;
}else
if(target < nums[mid]
)else
if(target > nums[mid])}
return-1
;}};
假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉。
( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。
搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 -1 。
你可以假設陣列中不存在重複的元素。
你的演算法時間複雜度必須是 o(log n) 級別。
示例 1:
輸入: nums = [4,5,6,7,0,1,2], target = 0
輸出: 4
示例 2:
輸入: nums = [4,5,6,7,0,1,2], target = 3
輸出: -1
分析:同樣還是需要思考+舉例
旋轉陣列是個新概念,也一定有屬於自己的特點。通過示例和舉例,發現旋轉陣列的特點:如果區間[0, mid]和[mid, nums.size()-1]至少有乙個是單調遞增的。
如果對示例1使用二分查詢,mid 會一直向左更新,不會找到0;原因在於[4,5,6,7]恰好是遞增的。所以,現在問題變成,如何更新mid,使得程式能夠找到traget = 0;
先結合1.旋轉陣列的特點,確定target屬於[0, mid]和[mid, nums.size()-1]哪個區間。然後在所屬區間上進行mid更新操作。
class
solution
else
}else
if(nums[mid]
<= nums[end]
)else}}
return-1
;}};
二分查詢的實質就是不斷更新mid,然後來鎖定要找的target; 而mid的更新是通過begin和end來決定的, begin和end的更新決定下乙個mid值位於當前mid的左端還是右端。
1.1和1.2是通過對mid左右附近值的限定來實現target的查詢;
1.3是通過對mid更新方向的選擇來實現target的查詢。
↩︎ ↩︎
↩︎↩︎↩︎
↩︎
二分搜尋基礎演算法
分治演算法基本思想 將乙個規模為 n 的問題分解為 k 個規模較小的子問題,這些子問題相互獨立且與原問題相同 給定已排好序的 n 個元素 array 0 n 1 現要在這 n 個元素找出特定元素x 首先較容易想到的是用順序搜尋方法,逐個比較 array 0 n 1 中元素,直至找出元素 x 或搜尋整...
基礎程式設計 二分查詢
題目要求 本題要求實現二分查詢演算法。函式介面定義 position binarysearch list l,elementtype x 其中list結構定義如下 typedef int position typedef struct lnode list struct lnode l是使用者傳入的...
java基礎 二分搜尋法
每個人寫的二分搜尋法均不相同,非常有趣,自己在工作中寫過的乙個二分搜尋法,當然前提是資料已經是有序的,並且目標很明確,最大程度的降低比較次數,這個演算法的難點在於程式的結束條件的尋找。public static boolean dichotomysearch int datas,int target...