LeetCode34、在排序數組中查找元素的第一個和最後一個位置

題目描述:

給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。

你的算法時間複雜度必須是 O(log n) 級別。

如果數組中不存在目標值,返回 [-1, -1]。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
著作權歸領釦網絡所有。

栗子1:

輸入: nums = [5,7,7,8,8,10], target = 8

輸出: [3,4]

栗子2:

輸入: nums = [5,7,7,8,8,10], target = 6

輸出: [-1,-1]

思路:

看到題目之後,你最先想到的可能是for循環去遍歷,可是本題對時間複雜度有一定的要求,所以此路不通。

時間複雜度必須是O(log n) ,再加上數據結構是升序排列的數組,那麼很容易就聯想到二分查找算法了。有沒有“柳暗花明又一村”的感覺呢?

不過讀完題之後,你會發現這和我們當初學習的二分查找還不太一樣。當初二分查找返回的是目標值所在數組對應的下標,不存在則返回-1。所以呢,本題是二分查找的一個變形題目。如果你不清楚最基礎的二分查找,可以先去看一下資料,之後再看這道題就會事半功倍。

這裏呢,我認爲你已經瞭解了二分查找算法,所以主要來講一下尋找目標值的一些情況。數組的默認值最後說明哈,我們先從中間值左面的檢索說起。中間值爲mid,前一個元素就是mid-1,當mid-1=0的時候說明mid前面是有值的,屬於需要檢索的範圍,如果mid-1<0,那麼便超出了邊界,可以終止檢索。因爲我們要找的是目標值第一次出現的位置,所以值需要等於目標值,在滿足這兩個條件的情況下進行檢索。從中間值向右的檢索也是一個道理。如果檢索的過程中,發現了目標值,那麼皆大歡喜。我們把它放到結果數組中即可,可是要是沒找到怎麼辦呢?

如果中間值的左面和右面都沒有目標值,那麼我們返回什麼呢?當然是{mid,mid}了,爲什麼?因爲只有nums[mid]==target目標值的時候纔會走進這個else語句,而且只有一個目標值。就好像{1,2,3},target=2;也有可能左面會有返回值,右面沒有,就像{0,2,2,3,4},target=2;也有可能右面會有返回值,左面沒有,就像{0,1,2,2,3},target=2。這樣子是不是就可以想通了?

如果有什麼錯誤或者問題,歡迎評論,我們一起探討,一起進步。

代碼:

public static int[] searchRange(int[] nums, int target) {
    int low = 0;
    int high = nums.length - 1;
    while (low <= high) {
        int mid = low + ((high - low) >> 1);
        if (nums[mid] < target) {
            low = mid + 1;
        } else if (nums[mid] > target) {
            high = mid - 1;
        } else {
            //注意
            int[] a = {mid, mid};
            //中間值向左檢索(不包含中間值)
            int tmp = mid - 1;
            while (tmp >= 0 && nums[tmp] == target) {
                a[0] = tmp;
                tmp--;
            }
            //中間值向右檢索(不包含中間值)
            tmp = mid + 1;
            while (tmp <= nums.length - 1 && nums[tmp] == target) {
                a[1] = tmp;
                tmp++;
            }
            //最終結果
            return a;
        }
    }
    return new int[]{-1, -1};
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章