Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务活动详情
一、题目描述
给定一个 M * N 的数字 f , f[i][j] 的值为 i * j , 给定一个数字 k , 求数组中第 k 大的数是多少
数据范围
M 、 N <= 30000
二、思路分析
朴素做法: 直接暴力,复杂度爆表。
不朴素做法: 显然可见,最终的答案是有单调性的,也就是说 k 越大,会使得答案增大。这也就使得我们能够用二分答案的方法。如何验证mid是否正确呢? 我们用 n/mid 可以直接计算出每一行有多少个小于等于 mid 的数字,也就是每次验证只需要O(n)的花费,可以接受。
三、AC代码
class Solution {
public:
int check(int mid,int m,int n) {
int tot=0;
for (int i=1; i<=m; i++) {
tot += min(n, mid/i);
}
return tot;
}
int findKthNumber(int m, int n, int k) {
int l=1,r=m*n;
int ans = 999999999;
while (l<=r) {
int mid = (l+r) / 2;
if (check(mid,m,n) >= k) {
ans = mid;
r = mid -1;
} else {
l = mid + 1;
}
}
return ans;
}
};
四、总结
一开始想复杂了,卡在如何验证mid那里,结果发现只需要计算每一行有多少个,再加起来就行了。