[Swift]LeetCode658. 找到 K 个最接近的元素 | Find K Closest Elements

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10485967.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

Given a sorted array, two integers k and x, find the kclosest elements to x in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred.

Example 1:

Input: [1,2,3,4,5], k=4, x=3
Output: [1,2,3,4] 

Example 2:

Input: [1,2,3,4,5], k=4, x=-1
Output: [1,2,3,4] 

Note:

  1. The value k is positive and will always be smaller than the length of the sorted array.
  2. Length of the given array is positive and will not exceed 104
  3. Absolute value of elements in the array and x will not exceed 104

UPDATE (2017/9/19):
The arr parameter had been changed to an array of integers(instead of a list of integers). Please reload the code definition to get the latest changes.


给定一个排序好的数组,两个整数 k 和 x,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。如果有两个数与 x 的差值一样,优先选择数值较小的那个数。

示例 1:

输入: [1,2,3,4,5], k=4, x=3
输出: [1,2,3,4] 

示例 2:

输入: [1,2,3,4,5], k=4, x=-1
输出: [1,2,3,4] 

说明:

  1. k 的值为正数,且总是小于给定排序数组的长度。
  2. 数组不为空,且长度不超过 104
  3. 数组里的每个元素与 x 的绝对值不超过 104 

更新(2017/9/19):
这个参数 arr 已经被改变为一个整数数组(而不是整数列表)。 请重新加载代码定义以获取最新更改。


Runtime: 328 ms
Memory Usage: 19.8 MB
 1 class Solution {
 2     func findClosestElements(_ arr: [Int], _ k: Int, _ x: Int) -> [Int] {
 3         var left:Int = 0
 4         var right:Int = arr.count - k
 5         while(left < right)
 6         {
 7             var mid:Int = left + (right - left) / 2
 8             if x - arr[mid] > arr[mid + k] - x
 9             {
10                 left = mid + 1
11             }
12             else
13             {
14                 right = mid
15             }
16         }
17         return Array(arr[left..<(left + k)])
18     }
19 }

336ms

 1 class Solution {
 2     func findClosestElements(_ arr: [Int], _ k: Int, _ x: Int) -> [Int] {
 3         if arr.count < 2 {
 4             return arr
 5         }
 6         
 7         let count = arr.count
 8         var closest = 0
 9         var minDiff = Int.max
10         var left = 0
11         var right = 0
12         var result = [Int]()
13         
14         for i in 0..<count {
15             let diff = abs(arr[i] - x)
16             if diff < minDiff || arr[i] == x {
17                 closest = i
18                 minDiff = diff
19             }
20         }
21         
22         left = closest
23         right = closest
24         while right - left + 1 < k {
25             if left - 1 < 0 {
26                 right += 1
27             } else if right + 1 > (count - 1) {
28                 left -= 1
29             } else if abs(x - arr[left - 1]) <= abs(x - arr[right + 1]) {
30                 left -= 1
31             } else {
32                 right += 1
33             }
34         }
35         
36         for i in left...right {
37             result.append(arr[i])
38         }
39         
40         return result
41     }
42 }

372ms

 1 struct Span {
 2     var start: Int
 3     var end: Int
 4     var mid: Int {
 5         return start + ((end - start) / 2)
 6     }
 7     var inverted: Bool {
 8         return end < start
 9     }
10     func leftRange() -> Span {
11         return Span(start: start, end: mid - 1)
12     }
13     func rightRange() -> Span {
14         return Span(start: mid + 1, end: end)
15     }
16 }
17 
18 
19 class Solution {
20     func findClosestIndex(arr: [Int], x: Int, span: Span) -> Int {
21         let mid = span.mid
22         
23         if mid == arr.count - 1 { return mid }
24         if mid <= 0 { return 0 }
25         
26         let midVal = arr[mid]
27         let nextVal = arr[mid + 1]
28         if midVal <= x && nextVal >= x {
29             return abs(x - midVal) <= abs(x - nextVal) ? mid : mid + 1
30         } else if midVal < x {
31             return findClosestIndex(arr: arr, x: x, span: span.rightRange())
32         } else {
33             return findClosestIndex(arr: arr, x: x, span: span.leftRange())
34         }
35     }
36     
37     func findClosestElements(_ arr: [Int], _ k: Int, _ x: Int) -> [Int] {
38         let startSpan = Span(start: 0, end: arr.count - 1)
39         let index = findClosestIndex(arr: arr, x: x, span: startSpan)
40         var left = index - 1
41         var right = index + 1
42         var returnVals: [Int] = [arr[index]]
43         for _ in 1..<k {
44             let rightVal = right < arr.count ? arr[right] : 10000000
45             let leftVal = left >= 0 ? arr[left] : 100000000
46             if abs(x - leftVal) <= abs(x - rightVal) {
47                 returnVals.append(leftVal)
48                 left -= 1
49             } else {
50                 returnVals.append(rightVal)
51                 right += 1
52             }
53         }
54         return returnVals.sorted()
55     }
56 }

416ms

 1 class Solution {
 2     
 3     func findStartIndex(_ arr: [Int], _ x: Int) -> Int {
 4         var i = 0
 5         while i < arr.count && arr[i] <= x {
 6             i += 1
 7         }
 8         
 9         return i
10     }
11     
12     func findClosestElements(_ arr: [Int], _ k: Int, _ x: Int) -> [Int] {
13         
14         var closest:[Int] = []
15         let startIndex = findStartIndex(arr, x)
16         var leftRunner:Int = startIndex - 1
17         var rightRunner:Int = startIndex
18         
19         while closest.count < k && (leftRunner >= 0 || rightRunner < arr.count) {           
20              
21             if leftRunner < 0 {
22                 closest.append(arr[rightRunner])
23                 rightRunner += 1
24                 continue
25             } else if rightRunner >= arr.count {
26                 closest.insert(arr[leftRunner], at: 0)
27                 leftRunner -= 1
28                 continue
29             }
30             
31             let left = arr[leftRunner]
32             let right = arr[rightRunner]
33             
34             if abs(x-left) <= abs(x-right) {
35                 closest.insert(left, at: 0)
36                 leftRunner -= 1
37             } else {
38                 closest.append(right)
39                 rightRunner += 1
40             }
41         }
42         
43         return closest
44     }
45 }

436ms

 1 class Solution {
 2     func findClosestElements(_ arr: [Int], _ k: Int, _ x: Int) -> [Int] {
 3         var res = [Int]()
 4         if x <= arr.first! {
 5             return Array(arr[0..<k])
 6         }
 7         if x >= arr.last! {
 8             return Array(arr[(arr.count - k)...])
 9         }
10         let index = binarySearch(arr, x)
11         var left = index - 1
12         var right = index + 1
13         res.append(arr[index])
14         while res.count < k {
15             if left < 0 {
16                 while res.count != k {
17                     res.append(arr[right])
18                     right += 1
19                 }
20                 break
21             } else if right >= arr.count {
22                 while res.count != k {
23                     res.append(arr[left])
24                     left -= 1
25                 }
26                 break
27             } else {
28                 if (x - arr[left]) <= (arr[right] - x) {
29                     res.append(arr[left])
30                     left -= 1
31                 } else {
32                     res.append(arr[right])
33                     right += 1
34                 }
35             }
36         }
37         return res.sorted()
38     }
39     
40     private func binarySearch(_ arr: [Int], _ x: Int) -> Int {
41         var left = 0
42         var right = arr.count - 1
43         while left < right {
44             let mid = left + (right - left)/2
45             if arr[mid] == x {
46                 return mid
47             } else if arr[mid] > x {
48                 right = mid - 1
49             } else {
50                 left = mid + 1
51             }
52         }
53         return left
54     }
55 }
原文地址:https://www.cnblogs.com/strengthen/p/10485967.html