LeetCode題解:在排序數組中查找元素的第一個和最後一個位置

在排序數組中查找元素的第一個和最後一個位置(middle)

一、題目

LeetCode 34.在排序數組中查找元素的第一個和最後一個位置

給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置,如果數組中不存在目標值 target,返回 [-1, -1]。

你可以設計並實現時間複雜度爲 O(log n) 的算法解決此問題嗎?

示例 1:

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

示例 2:

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

提示:

  • nums 是一個非遞減數組

二、基礎模版 III

因爲我們的判斷區間最少爲2個元素,所以我們要注意循環的執行條件

  1. 簡單的判斷邊界: nums.length === 0,return -1
  2. 定義初始的左右邊界:left = 0, right = nums.length - 1
  3. 確定執行條件:left + 1 < right,這也意味着查找區間要存在 3 個元素;
  4. 向左查找時:right = mid
  5. 向左查找時:left = mid
  6. 判斷剩下的兩個元素哪個符合目標元素,並返回結果;

三、題解

分析模版

  • 我們的目標是:尋找目標值的起始下標和終止下標,但它是可能重複的
  • 針對這樣的情況,我們要將判斷拆解成查找目標首次出現的位置,和最後一次出現的位置\
  • 我們講一個大問題,用拆分成2個小問題,並用二分但解決對應的問題
var searchRange = function(nums, target) {
   
   
    const NO_TARGET = [-1, -1];
    if (nums.length === 0) return NO_TARGET;
    // 判斷首次位置
    let firstPosition = findFirstPos(nums, target);
    if (firstPosition < 0) return NO_TARGET;
    // 獲取最終出現位置
    let lastPostion = findLastPos(nums, target);
    return [firstPosition, lastPostion];
};
// 首次出現目標位置,參考模板II
const findFirstPos = function(nums, target) {
   
   
    let left = 0;
    let right = nums.length - 1;

    while (left < right) {
   
   
        let mid = left + ((right - left) >> 1);
        if (nums[mid] === target) {
   
   
            right = mid; // 捨棄右側,留mid,不管右側是否有重複值,我們只留1個滿足條件的
        } else if (nums[mid] > target) {
   
   
            right = mid - 1; // 直接捨棄
        } else {
   
   
            left = mid + 1; // 直接捨棄
        }
    }
    if (nums[left] === target) return left;
    return -1;
}
// 首次出現目標位置,參考模板II
const findLastPos = function(nums, target) {
   
   
    let left = 0;
    let right = nums.length - 1;
    while (left < right) {
   
   
        let mid = left + ((right - left + 1) >> 1); // 注意這裏 + 1是爲了向上取整,因爲我們要查找最後出現的元素
        if (nums[mid] === target) {
   
   
            left = mid; // 捨棄右側,留mid
        } else if (nums[mid] > target) {
   
   
            right = mid - 1; // 直接捨棄
        } else {
   
   
            left = mid + 1;
        }
    }
    if (nums[left] === target) return left;
    return -1;
}

四、寫在最後

本文是二分查找-模版III 的第一題,後面的幾道題的也算是本模版的微調版,加油~

如果對你有所幫助不妨給本項目的github 點個 star,這是對我最大的鼓勵

關於我

  • 花名:餘光
  • WX:j565017805
  • 沉迷 JS,水平有限,虛心學習中

其他沉澱

````
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章