【LeetCode 668】Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务

81 阅读1分钟

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那里,结果发现只需要计算每一行有多少个,再加起来就行了。