二维里的二分查找!拼多多笔试5|刷题打卡

469 阅读1分钟

掘金团队号上线,助你 Offer 临门! 点击 查看详情

一、题目描述:

image.png

二、思路分析:

这题看起来很明显,是个排序嘛。直接扔优先队列里在pop()一遍就可以了 代码如下

#include<queue>
#include<iostream>

using namespace std;
int main(){
    priority_queue<int> q;
    int n , m ,k;
    cin >> n >> m >> k;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            q.push(i *j);
        }
    }
    while(k > 1){
        k--;
        q.pop();
        
    }
    cout << q.top() << endl;
    return 0;
}

直接超时,内存消耗过大 那就是不能都存下来,也就是不能用排序解决这问题

剪枝第一时间就应该想到二分法,二分法的重点在于结果

即:我不考虑要如何排序,而是从结果上思考。

  1. 题目问的是第k大的值,数的范围为1~m*n 之间.
  2. 我们假设答案为x,如果有k - 1个值大于x的话
  3. 那么,如果数据中有x,则答案为x

三、AC 代码:

    int left = 1;
    int right = m * n;
    k = m * n - k + 1;
    while (left < right) {
        // 注意int类型溢出问题!
        int mid = (int)(((long)left + right) / 2);
        // 求小于等于 mid 的数量
        int row = mid / m;
        int count = row * m;
        for (int i = row + 1; i <= n; i++) {
            count += mid / i;
        }
        if (count < k) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }

四、总结:

二分法的思路向来是和其他题干不同的,讲道理这五道题我也没看到哪道题出的中规中矩,看起来拼多多相对于数据结构的掌握,更会考察答题思路多一点。