1. 程式人生 > 實用技巧 ># LeetCode 34 在排序陣列中查詢元素的第一個和最後一個位置

# LeetCode 34 在排序陣列中查詢元素的第一個和最後一個位置

LeetCode 34 在排序陣列中查詢元素的第一個和最後一個位置

問題描述:
  給定一個按照升序排列的整數陣列 nums,和一個目標值 target。找出給定目標值在陣列中的開始位置和結束位置。
  你的演算法時間複雜度必須是 O(log n) 級別。
  如果陣列中不存在目標值,返回 [-1, -1]。

執行用時:0 ms, 在所有 Java 提交中擊敗了100.00%的使用者
記憶體消耗:41.9 MB, 在所有 Java 提交中擊敗了70.19%的使用者

二分查詢

  1. 使用二分查詢,若mid不是target則向左、右二分
  2. (第一次出現位置)若mid恰好是target,且向左人為target,則將right設為mid-1繼續二分
  3. 反之mid處即為第一次出現位置,返回該位置
  4. target最後一次出現位置搜尋方式同上
class Solution {
    public int[] searchRange(int[] nums, int target) {
        /*邊界情況*/
        if(nums==null || nums.length==0) 
            return new int[]{-1,-1};
        if(nums.length==1) 
            return nums[0]==target? new int[]{0,0}:
                        new int[]{-1,-1};
        /*改進的二分查詢*/
        int[] ans = new int[2];
        Arrays.fill(ans, -1);
        int lIdx = 0, rIdx = nums.length-1;
        /*找到最左*/
        while(lIdx <= rIdx){
            int midIdx = lIdx + (rIdx-lIdx)/2;
            /*中間相等且左邊相等*/
            if(nums[midIdx]==target)
                if(midIdx>lIdx && nums[midIdx-1]==target)
                    rIdx = midIdx-1;
                else{
                    ans[0] = midIdx;
                    break;
                }
            /*二分*/
            else if(nums[midIdx] > target)
                rIdx = midIdx-1;
            else
                lIdx = midIdx+1;
        }
        /*找到最右*/
        lIdx = 0; rIdx = nums.length-1;
        while(lIdx <= rIdx){
            int midIdx = lIdx + (rIdx-lIdx)/2;
            /*中間相等且右邊相等*/
            if(nums[midIdx]==target)
                if(midIdx<rIdx && nums[midIdx+1]==target)
                    lIdx = midIdx+1;
                else{
                    ans[1] = midIdx;
                    break;
                }
            /*二分*/
            else if(nums[midIdx] > target)
                rIdx = midIdx-1;
            else
                lIdx = midIdx+1;
        }

        return ans;
    }
}