973. K Closest Points to Origin

该博客讨论了如何找到平面上K个距离原点最近的点。提供了两种方法:完全排序和分治策略,详细解释了每种方法的时间和空间复杂度,并给出了Go语言的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

973. K Closest Points to Origin
We have a list of points on the plane. Find the K closest points to the origin (0, 0).
(Here, the distance between two points on a plane is the Euclidean distance.)
You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.)

Example 1:
Input: points = [[1,3],[-2,2]], K = 1
Output: [[-2,2]]
Explanation:
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]].

Example 2:
Input: points = [[3,3],[5,-1],[-2,4]], K = 2
Output: [[3,3],[-2,4]]
(The answer [[-2,4],[3,3]] would also be accepted.)

Note:
1 <= K <= points.length <= 10000
-10000 < points[i][0] < 10000
-10000 < points[i][1] < 10000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/k-closest-points-to-origin
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

Thought and method:

1、Totally Sort
Sort all the distances from the origin, and output the nearest K points. It is most easiest to think of and transfer it into codes.However, it perfomance bad in the time consume due to the need in sorting.

Time complexity: O(nlogn)
Space complexity: O(n)

2、divide-and-conquer method
Condering that the first process to influence the time complexity is the sorting, we mainly do some change in decreasing the numbers which we have to send into the sorting.

We randomly select an element x and divide the array into two parts: one that is less than x from the origin, and one that is greater than x from the origin. Thus we can reduce the size of the problem by half each time.

We can have a function called Work that does partial quicksort by selecting a random element pos as the tag and then using this element to divide the array into two parts.

Then, we have two parts [i, pos] and [pos+1, j]
if K < pos, we just call work on the first part.
If K >pos, then the first part needs to be selected, we need to call work on the second part.

average Time complexity: O(n)
Space complexity: O(n)

code
1、
we do not need to also calculate the square root of the value, the square of the value is enough.

func kClosest(points [][]int, K int) [][]int {
    
    sort.Slice(points, func(i, j int) bool{
        return float64(points[i][0]*points[i][0] + points[i][1]*points[i][1]) < float64(points[j][0]*points[j][0] + points[j][1]*points[j][1])
    })
    return points[:K]
}

2、At the beginning of this section, I was influenced by the official documents.
"random element" "Part of the sort"and also "using two pointer"
After a number of failures, I realized that using the exact same idea would not work in GO, given that the use of including Pointers is not as flexible as it is in Java and Python.
After consulting the following sources, I realized that using only a pointer to an array is better than two pointer with hard and complex calclulating and codes.

link.

func kClosest(points [][]int, K int) [][]int {
    result := [][]int{}
    kClosestHelper(points,K,&result)
    return result
}

func kClosestHelper(points [][]int, K int,result *[][]int) *[][]int {
    start,end := 0,len(points)-1
    pos := work(points,start,end)
    //pos is the sign 
    //pos < K-1 consider the whole left part of pos and part of points in the right part
    if pos < K-1 {
        *result = append(*result,points[:pos+1]...)
        return kClosestHelper(points[pos+1:],K-pos-1,result)
    }
    //consider the only left part of pos
    if pos > K-1{
        return kClosestHelper(points[:pos],K,result)       
    }
    //else result
    *result = append(*result,points[:pos+1]...)
    return result
}

//part quick sort
func work(nums [][]int, start,end int) int{
    pos,left,right := nums[start],start,end
    for (left < right){
        for (distance(nums[right]) >= distance(pos) && left<right) {
            right--
        }
        for (distance(nums[left]) <= distance(pos) && left<right) {
            left++
        }
        nums[left],nums[right] = nums[right],nums[left]
    }
    nums[start],nums[left] = nums[left],nums[start]
    return left
}

//calculate
func distance(num []int)int{
    return num[0] * num[0] + num[1] * num[1]
}

test
Example 1:
Input: points = [[1,3],[-2,2]], K = 1
在这里插入图片描述

Example 2:
Input: points = [[3,3],[5,-1],[-2,4]], K = 2
在这里插入图片描述
As you can see that the former way is running much slower than the latters.
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值