題目:
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
從題目中獲取到關鍵字:sorted array ,find...position, a given target value, O(logn).
這些關鍵字都在提醒我們這道題的思路應該是二分查詢法。
二分查詢方法
二分查詢經常用來在有序的數列查詢某個特定的位置。
因此,應用二分查詢法,這個數列必須包含以下特徵:
- 儲存在陣列中
- 有序排列
同時這道題讓我們確定 starting position和ending position,這就讓我們聯想到之前做過的Search Insert Position一題,當無法查詢到given target時,利用非遞迴二分查詢法所得的最終low和high指標,將會指向該無法查詢到的元素的左右兩個元素。說不清楚看例子,例如,給定arraylist [1,2,4,5] target為3,那麼通過傳統非遞迴二分查詢法,low指標將會指向4(位置為2),high指標指向2(位置為1)。
利用這種規律,我們就能夠找到target元素的左右邊界。所以本題的解題思路為:
第一步,在給定陣列中找到該target,記錄該位置。這時我們並不關心這個target是邊界還是中間值,我們只需確定,在陣列中是能夠找到這樣一個target值。如果找不到返回{-1,-1}。為了保證時間複雜度是O(logn), 這裡自然而然使用傳統二分查詢法實現。
第二步,確定該target的右邊界。此時我們將對陣列從剛才確定的那個target的pos作為起始點,到陣列結束,來確定右邊界。同樣是使用二分查詢法,當新的mid值仍然等於target值時,我們能確定該mid左半邊(到pos)都是等於target,繼續在右半邊查詢。如果新的mid值不等於target值,我們就知道右邊界一定在新mid值的左半邊,繼續查詢。最後新的high指標指向的就是右邊界的位置。
第三步,確定該target的左邊界。這一步與第二步對稱操作,最後新的low指標指向的就是左邊界的位置。
最後,返回結果陣列。
程式碼如下:
2 int [] res = {-1,-1};
3 if(A == null || A.length == 0)
4 return res;
5
6 //first iteration, find target wherever it is
7 int low = 0;
8 int high = A.length-1;
9 int pos = 0;
10 while(low <= high){
11 int mid = (low + high)/2;
12 pos = mid;
13 if(A[mid] > target)
14 high = mid - 1;
15 else if(A[mid] < target)
16 low = mid + 1;
17 else{
18 res[0] = pos;
19 res[1] = pos;
20 break;
21 }
22 }
23
24 if(A[pos] != target)
25 return res;
26
27 //second iteration, find the right boundary of this target
28 int newlow = pos;
29 int newhigh = A.length-1;
30 while(newlow <= newhigh){
31 int newmid = (newlow+newhigh)/2;
32 if(A[newmid] == target)
33 newlow = newmid + 1;
34 else
35 newhigh = newmid - 1;
36 }
37 res[1] = newhigh;
38
39 //third iteration, find the left boundary of this target
40 newlow = 0;
41 newhigh = pos;
42 while(newlow <= newhigh){
43 int newmid = (newlow+newhigh)/2;
44 if(A[newmid] == target)
45 newhigh = newmid - 1;
46 else
47 newlow = newmid + 1;
48 }
49 res[0] = newlow;
50
51 return res;
52 }
Reference:http://blog.csdn.net/linhuanmars/article/details/20593391