持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。
怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~
一、题目描述:
-
题目内容
-
题目示例
-
题目解析
- 1 <= k <= arr.length
- 1 <= arr.length <= 104
- arr 按 升序 排列
- 104 <= arr[i], x <= 104
二、思路分析:
我们今天做一道Leetcode 中等 难度的题 找到K个最接近到元素。题目要求如同题目标题,找到按照指定规则的K元素,数组中元素a,b与之间需要满足如下:
|a-x| < |b-x||a - x| == |b - x|且a < b
根据题目要求,有如下五种方法可以进行解答,思路如下所示:
-
方法一:排序
- 题目要求找到最接近x的元素,因此可以对arr元素按照abs(a-x)进行排序
- arr按照绝对值排序后,对arr进行截取前k-1个数
- 本题要求返回的结果要按照升序排序,再调用sorted(arr[:k])
class Solution(object): def findClosestElements(self, arr, k, x): arr.sort(key= lambda a : abs(a-x)) return sorted(arr[:k]) -
方法二:删除最远的数
- 本题中要求出满足在x数组最近的k元素,我们可以逆向思路
- 删除掉|a-x| > |b-x|的元素,当arr的长度等于k时,则返回arr的结果
class Solution(object): def findClosestElements(self, arr, k, x): n = len(arr) while True: if n == k: return arr if abs(arr[0]-x) > abs(arr[n-1]-x): arr.remove(arr[0]) else: arr.remove(arr[n-1]) n -=1 -
方式三:双指针二分查找
- 由于数组arr是升序遍历的,我们可以借助双指针方法,找到|a-x| <=|b-x|的零界点
- [0,left]是小于x的,[right,n-1]是大于x的
- 当left和right指针分别指向arr索引位置0,n-1位置,mid则取(left+right)/2
- x-arr[left]>arr[right]-x时则left被赋值为mid+1,否则right指针向左移一步
- 直到right指针小于left时,退出循环返回arr[left:left+k]
class Solution(object): def findClosestElements(self, arr, k, x): left = 0 right = len(arr)-k while left < right: mid = (left + right)/2 if x-arr[mid] > arr[mid+k]-x : left = mid +1 else: right = mid return arr[left:left+k] -
方法四:bisect_left()二分查找
- 在python中,我们可以借用bisect_left()方法找到x数在arr最近的索引位置,赋值给right
- left指针则赋值right指针左边一位
- 使用for循环遍历取k次,找到left,right的位置
- 当left小于0时,则right指针向右边移一位
- 当right指针大于等于len(arr)或者x-arr[left]<=arr[right]-x时,则left-1
class Solution(object): def findClosestElements(self, arr, k, x): right = bisect_left(arr, x) left = right - 1 for _ in range(k): if left < 0: right += 1 elif right >= len(arr) or x - arr[left] <= arr[right] - x: left -= 1 else: right += 1 return arr[left+1:right]
三、总结:
本题考察在数组中使用二分法运用,需要找到满足要求的双指针位置,AC提交记录如下:
- 时间复杂度:O(logn+k),n为arr的长度
- 空间复杂度:O(1),没有使用额外空间
以上是本期内容,欢迎大佬们点赞评论,下期见~~~