658. 找到 K 个最接近的元素:二分法

469 阅读3分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第5篇文章,点击查看活动详情

本次刷题日记的第 106 篇,力扣题为:658. 找到 K 个最接近的元素

一、题目描述:

继续来刷每日一题,找到 K 个最接近的元素,看需要我们如何去实现

二、这道题考察了什么思想?你的思路是什么?

题目的意思很明确,

  • 第一给出我们一个 arr 排序数组,里面都是整型数字
  • 第二给出了 x 的值,需要我们在数组 arr 中找到和 x 差值绝对值最小的 k 个数字,且这 k 数字需要以升序排序好,返回结果

分析

如何去思考这个题目呢?咱们直接从需求出发

题目既然说了 arr 数组是排序好的,又要我们找到数组中和 x 差值要尽可能的小,那么咱们必然要找到 arr 数中和 x 差值绝对值最小的一个数对应的位置

这个时候,问题就来到如何查找 arr 数组中与 x 差值绝对值最小的数字了

  • 简单的可以使用遍历的方式来找到
  • 也可以使用二分查找的方式来查找最接近 x 的数字和其索引

另外,找到这个数字和其对应的索引之后,我们接下来就需要考虑,如何在这个基础上再找 k 个数字(包含当前找到的) 也尽可能的满足和 x 的差值的绝对值最小

那么,我们可以这样来找

咱们在数组中找到离 x 最近的数字 3 ,然后在向两边找,如果左边的值如 left 和 x 的差值的绝对值 小于 右边 right 和 x 差值的绝对值,则左边继续找,否者右边继续找

当然如果咱们找到左边的边界,或者右边的边界的时候,就往对方的方向去找,直到找到 k 个数即可

最终返回 left 到 right 中间的数字即是我们要找的 k 个数字

那么接下来就来手撸代码吧

三、编码

根据上述逻辑和分析,我们就可以翻译成如下代码

编码如下:

func findClosestElements(arr []int, k int, x int) []int {
    // 找到 x 所在的 arr 中最近的一个索引
    right := sort.SearchInts(arr, x)
    left := right-1

    for ;k>0; k-- {
        if left < 0{
            right++
        }else if right >= len(arr)  || x - arr[left] <= arr[right] - x{
           left--
        }else{
            right++
        }
    }
    return arr[left+1:right]
}

四、总结:

本次咱们这种实现的方式是,先通过二分法去查找离 x 最近的数,然后再遍历 k 次,因此咱们的时间复杂度是 O(logn + k)

咱们没有引入额外其他数量级的空间消耗,因此时间复杂度是 O(1)

原题地址:658. 找到 K 个最接近的元素

今天就到这里,学习所得,若有偏差,还请斧正

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

暂时无法在文档外展示此内容