题意就不说了,leetcode 上都有。
这道题首先想到的是将距离算出来sort后取前K(好像这样也能过),后来又想到了前一阵子刚看的快速选择,经过选择挑好第K大的值时,K即是值也是索引,所以索引K前的便是前K个最小距离。相比于快排能够少排后半部分节省时间。
刚开始想到这样做的时候直接上手就开始写了,当时用一个map存储距离(key)和点(value)的关系,但是发现距离重复的情况下会有覆盖的情况([-1,1]和[1,-1]距离都是2),又想到把key-value反过来存储,好嘛踩坑了key不能存储slice(基础不行啊,因为之前一直用C++,思路还没转过来,C++中的multiset或者unordered_map<pair<int, int>, int>解决了),最后决定map存储原points每个point的索引(key)和距离(value),通过快速选择把距离最小的K个points索引选出来,放到返回切片里返回。
结果好像还可以,潜意识里觉得不用这样做有更好的方法,但是不想细琢磨了,今天也是个lazyboy。
执行用时 : 928 ms, 在K Closest Points to Origin的Go提交中击败了92.86% 的用户
内存消耗 : 65.6 MB, 在K Closest Points to Origin的Go提交中击败了100.00% 的用户
func kClosest(points [][]int, K int) [][]int { if len(points) == K { return points } var v []int var re [][]int m := make(map[int]int) for i:=0;i<len(points);i++ { m[i] = points[i][0]*points[i][0] + points[i][1]*points[i][1] v = append(v, i) } findK(m, v, 0, len(v)-1, K) for i:=0;i<K;i++ { re = append(re, points[v[i]]) } return re; } func findK(m map[int]int, s []int, start, end, k int) { p := m[s[end]] l := start for i:=start; i<end; i++ { if m[s[i]] < p { s[l], s[i] = s[i], s[l] l++ } } s[l], s[end] = s[end], s[l] if k == l { return } else if l < k { findK(m, s, l+1, end, k) } else { findK(m, s, start, l-1, k) } }
记录每天解决的一点小问题,积累起来就能解决大问题。