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

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

earch ast 繼續 pri rst not 找到 fin 存在

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm‘s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

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

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

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

示例 1:

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

示例 2:

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

【二進制搜索】

直覺

因為數組已排序,我們可以使用二進制搜索來定位最左邊和最右邊的索引。

算法

除了用於查找最左側和最右側索引本身的子例程之外,整體算法與線性掃描方法的工作方式非常相似。在這裏,我們使用修改後的二進制搜索來搜索已排序的數組,並進行一些小的調整。首先,因為我們正在找到最左邊(或最右邊)的索引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 }
 

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