★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-qffzyxpr-me.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target
value.git
Your algorithm's runtime complexity must be in the order of O(log n).github
If the target is not found in the array, return [-1, -1]
.算法
Example 1:數組
Input: nums = [, target = 8 Output: [3,4]5,7,7,8,8,10]
Example 2:微信
Input: nums = [, target = 6 Output: [-1,-1]5,7,7,8,8,10]
給定一個按照升序排列的整數數組 nums
,和一個目標值 target
。找出給定目標值在數組中的開始位置和結束位置。動畫
你的算法時間複雜度必須是 O(log n) 級別。spa
若是數組中不存在目標值,返回 [-1, -1]
。code
示例 1:htm
輸入: nums = [, target = 8 輸出: [3,4]5,7,7,8,8,10]
示例 2:
輸入: nums = [, target = 6 輸出: [-1,-1]5,7,7,8,8,10]
【二進制搜索】
直覺
由於數組已排序,咱們可使用二進制搜索來定位最左邊和最右邊的索引。
算法
除了用於查找最左側和最右側索引自己的子例程以外,總體算法與線性掃描方法的工做方式很是類似。在這裏,咱們使用修改後的二進制搜索來搜索已排序的數組,並進行一些小的調整。首先,由於咱們正在找到最左邊(或最右邊)的索引target
(而不是返回true
咱們找到的iff target
),因此算法一找到匹配就不會終止。相反,咱們繼續搜索,直到lo == hi
它們包含一些target
能夠找到的索引。
另外一個變化是引入left
參數,這是一個布爾值,表示在事件中要作什麼target == nums[mid]
; 若是 left
是true
,那麼咱們在關係上的左子陣列上「遞歸」。不然,咱們走對了。要了解爲何這是正確的,請考慮咱們target
在索引處找到的狀況 i
。最左邊target
不能出現任何大於的索引i
,所以咱們永遠不須要考慮正確的子陣列。相同的參數適用於最右邊的索引。
下面的第一個動畫顯示了查找最左側索引的過程,第二個動畫顯示了查找最右側索引的索引右側的過程。
68ms
1 class Solution { 2 func searchRange(_ nums: [Int], _ target: Int) -> [Int] { 3 var targetRange:[Int] = [-1, -1] 4 var leftIdx:Int = extremeInsertionIndex(nums, target, true) 5 6 // 聲明`leftIdx` 在數組的邊界內而且是 `target` 7 // 實際上在`nums`中 8 if leftIdx == nums.count || nums[leftIdx] != target 9 { 10 return targetRange 11 } 12 13 targetRange[0] = leftIdx 14 targetRange[1] = extremeInsertionIndex(nums, target, false) - 1 15 16 return targetRange 17 } 18 19 // 返回 `target`應該是最左邊(或最右邊)的索引 20 // 經過二進制搜索插入排序數組'nums'. 21 func extremeInsertionIndex(_ nums: [Int], _ target: Int,_ left:Bool) -> Int 22 { 23 var lo:Int = 0 24 var hi:Int = nums.count 25 26 while (lo < hi) 27 { 28 var mid:Int = (lo + hi) / 2 29 if nums[mid] > target || (left && target == nums[mid]) 30 { 31 hi = mid 32 } 33 else 34 { 35 lo = mid+1 36 } 37 } 38 return lo 39 } 40 }
12ms
1 class Solution { 2 func searchRange(_ nums: [Int], _ target: Int) -> [Int] { 3 let start = binarySearch(nums, target) 4 5 if start == nums.count || nums[start] != target { 6 return [-1, -1] 7 } 8 9 let end = binarySearch(nums, target + 1) - 1 10 11 return [start, end] 12 } 13 14 private func binarySearch(_ nums: [Int], _ target: Int) -> Int { 15 var left = 0 16 var right = nums.count 17 18 while left < right { 19 let middle = left + (right - left) / 2 20 if nums[middle] < target { 21 left = middle + 1 22 } else { 23 right = middle 24 } 25 } 26 27 return left 28 } 29 }
16ms
1 class Solution { 2 func searchRange(_ nums: [Int], _ target: Int) -> [Int] { 3 var left = 0 4 var right = nums.count - 1 5 var mid = 0 6 var first = -1 7 8 // 尋找第一個出現target的位置 9 while left <= right { 10 mid = left + (right - left)/2 11 if nums[mid] >= target { 12 right = mid - 1 13 } else { 14 left = mid + 1 15 } 16 if nums[mid] == target { 17 first = mid 18 } 19 } 20 21 // 若是找不到第一個直接返回 22 if first == -1 { 23 return [first ,first] 24 } 25 26 // 尋找最後一個出現target的位置 27 var last = -1 28 left = first 29 right = nums.count - 1 30 while left <= right { 31 mid = left + (right - left)/2 32 if nums[mid] > target { 33 right = mid - 1 34 } else { 35 left = mid + 1 36 } 37 if nums[mid] == target { 38 last = mid 39 } 40 } 41 return [first,last] 42 } 43 }
16ms
1 class Solution { 2 func searchRange(_ nums: [Int], _ target: Int) -> [Int] { 3 4 if nums.count == 1 5 { 6 if nums[0] == target 7 { 8 return [0,0] 9 } 10 else{ 11 return [-1,-1] 12 } 13 } 14 var index = binarySearch(nums,0,nums.count-1,target) 15 print(index) 16 if index == -1 17 { 18 return [-1,-1] 19 } 20 let midIndex = index 21 var keepGoing = true 22 var startIndex = midIndex 23 while keepGoing 24 { 25 index -= 1 26 if index >= 0 27 { 28 if nums[index] == target 29 { 30 print("here") 31 startIndex = index 32 } 33 else{ 34 keepGoing = false 35 } 36 }else{ 37 keepGoing = false 38 } 39 } 40 41 keepGoing = true 42 var endIndex = midIndex 43 while keepGoing 44 { 45 index += 1 46 if index < nums.count 47 { 48 if nums[index] == target 49 { 50 print("here2") 51 endIndex = index 52 } 53 else{ 54 keepGoing = false 55 } 56 } 57 else{ 58 keepGoing = false 59 } 60 } 61 62 return [startIndex,endIndex] 63 } 64 65 func binarySearch(_ nums:[Int],_ lo:Int,_ hi:Int,_ target:Int)->Int 66 { 67 if lo == hi 68 { 69 if nums[lo] == target 70 { 71 return lo 72 } 73 else{ 74 return -1 75 } 76 } 77 if lo < hi 78 { 79 var mi = (lo+hi)/2 80 81 if nums[mi] == target 82 { 83 return mi 84 } 85 else if target < nums[mi] 86 { 87 return binarySearch(nums,lo,mi-1,target) 88 } 89 else if target > nums[mi] 90 { 91 return binarySearch(nums,mi+1,hi,target) 92 } 93 } 94 return -1 95 } 96 }
76ms
1 class Solution { 2 func searchRange(_ nums: [Int], _ target: Int) -> [Int] { 3 var startIndex: Int? 4 var endIndex: Int? 5 6 for (index, num) in nums.enumerated() { 7 if num == target { 8 if startIndex == nil { 9 startIndex = index 10 } 11 12 endIndex = index 13 } 14 } 15 16 if startIndex == nil { 17 return [-1, -1] 18 } else { 19 return [startIndex!, endIndex!] 20 } 21 } 22 }
104ms
1 class Solution { 2 func searchRange(_ nums: [Int], _ target: Int) -> [Int] { 3 var min = -1 4 var max = -1 5 for i in 0..<nums.count { 6 guard nums[i] == target else { 7 continue 8 } 9 if min == -1 { 10 min = i 11 } 12 max = i 13 } 14 return [min, max] 15 } 16 }