[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 k
closest 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:
- The value k is positive and will always be smaller than the length of the sorted array.
- Length of the given array is positive and will not exceed 104
- 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]
说明:
- k 的值为正数,且总是小于给定排序数组的长度。
- 数组不为空,且长度不超过 104
- 数组里的每个元素与 x 的绝对值不超过 104
更新(2017/9/19):
这个参数 arr 已经被改变为一个整数数组(而不是整数列表)。 请重新加载代码定义以获取最新更改。
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 }