前言
這題標準運用了二分搜尋法,演算法通常需要使用二分思想,即每次能夠排除一半的範圍,快速的找出陣列中所要求的元素位置,這樣時間複雜度可達 O(log n),時間複雜度可達 O(n),這裡有 JAVA 和 Python 的寫法。
題目
Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value. If target is not found in the array, return [-1, -1]. You must write an algorithm with O(log n) runtime complexity.
給定一個不是降序過後的整數陣列 nums,找到目標值的開始和結束的位置。 如果在陣列裡找不到目標,回傳 [-1, -1]。 你必須寫出一個時間複雜度 O(log n) 的算法。
題目連結:https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
題目限制
0 <= nums.length <= 105109 <= nums[i] <= 109nums is a non-decreasing array.109 <= target <= 109
範例
1 2 Input: nums = [5 ,7 ,7 ,8 ,8 ,10 ], target = 8 Output: [3 ,4 ]
目標值是 8,所以在陣列裡開始和結束的位置是 3 和 4
1 2 Input: nums = [5 ,7 ,7 ,8 ,8 ,10 ], target = 6 Output: [-1 ,-1 ]
1 2 Input: nums = [], target = 0 Output: [-1 ,-1 ]
思路&筆記
設計兩個函數 findFirst 、 findLast 來取得第一個和最後一個符合 target 值的索引。
兩個函數內都運用了二分搜尋法來找到正確的索引。
findFirst 函數:
如果目標元素 target 小於等於 nums[mid],則將 end 更新為 mid - 1。
如果目標元素 target 大於 nums[mid],則將 start 更新為 mid + 1。
在找到目標元素時,將 idx 設定為 mid。
確保在找到目標元素時繼續向左搜尋,以找到第一次出現的位置。
findLast 函數:
如果目標元素 target 大於等於 nums[mid],則將 start 更新為 mid + 1。
如果目標元素 target 小於 nums[mid],則將 end 更新為 mid - 1。
在找到目標元素時,將 idx 設定為 mid。
確保在找到目標元素時繼續向右搜尋,以找到最後一次出現的位置。
[注意點] 之所以要用上述中間值的寫法會比較安全,因如果 start 和 end 趨近於最大數時,兩者相加起來的合可能會造成整數溢位
JAVA 實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Solution { public int [] searchRange(int [] nums, int target) { int [] result = new int [2 ]; result[0 ] = findFirst(nums, target); result[1 ] = findLast(nums, target); return result; } public int findFirst (int [] nums, int target) { int idx = -1 ; int start = 0 ; int end = nums.length - 1 ; while (start <= end){ int mid = (start + end) / 2 ; if (target <= nums[mid]){ end = mid - 1 ; }else { start = mid + 1 ; } if (target == nums[mid]) { idx = mid; } } return idx; } public int findLast (int [] nums, int target) { int idx = -1 ; int start = 0 ; int end = nums.length - 1 ; while (start <= end){ int mid = (start + end) / 2 ; if (target >= nums[mid]){ start = mid + 1 ; }else { end = mid - 1 ; } if (target == nums[mid]){ idx = mid; } } return idx; } }
Python 實現
使用了和 Java 一樣的邏輯執行,換成 Python 的寫法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution : def searchRange (self, nums: List [int ], target: int ) -> List [int ]: result = [self.findFirst(nums, target), self.findLast(nums, target)] return result def findFirst (self, nums: List [int ], target: int ) -> int : idx = -1 start, end = 0 , len (nums) - 1 while start <= end: mid = (start + end) // 2 if target <= nums[mid]: end = mid - 1 else : start = mid + 1 if target == nums[mid]: idx = mid return idx def findLast (self, nums: List [int ], target: int ) -> int : idx = -1 start, end = 0 , len (nums) - 1 while start <= end: mid = (start + end) // 2 if target >= nums[mid]: start = mid + 1 else : end = mid - 1 if target == nums[mid]: idx = mid return idx
成績
Language
Runtime
Memory
Java
0ms
45.74MB
Python
75ms
17.81MB