Search for a Range leetcode java

愛做飯的小瑩子發表於2014-07-21

題目:

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指標指向的就是左邊界的位置。

最後,返回結果陣列。

 

程式碼如下:

 

 1     public int[] searchRange(int[] A, int target) {
 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

相關文章