[Swift]LeetCode34. 在排序數組中查找元素的第一個和最後一個位置 | Find First and Last Position of Element in Sorted Array

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(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]若是 lefttrue,那麼咱們在關係上的左子陣列上「遞歸」。不然,咱們走對了。要了解爲何這是正確的,請考慮咱們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 }
相關文章
相關標籤/搜索