LeetCode 668. Kth Smallest Number in Multiplication Table

https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/description/

一、题目:
给出一个 m*n 的乘法表,然后求出第k大的数字。
二、分析:
1、最开始的思路,是便利一下 m*n, 然后用 map 容器把每个节点出现的个数保存起来, map[node]++; 结果超时。
2、用Bs,进行查找,在 1~m*n 之间进行二分查找,如果 1~mid 之间不大于 k 的节点的个数大于 k, 则继续二分左半部分;反之,二分右半部分。
  其中最为纠结的就是在二分的时候,如何判断一个居间内 不大于 k 的节点个数。
三、map 容器的超时代码:

#include<iostream>
#include <map>
using namespace std;

#define MaxLen 30010
class Solution {
public:
    int findKthNumber(int m, int n, int k) {
        map<int, int>_map;
        _map.clear();
        for(int i=1; i<=m; i++){
            for(int j=1; j<=n; j++){
                int tmp = 0;
                if(i==1){
                    tmp = j;
                }else if(j==1){
                    tmp = i;
                }else{
                    tmp = i*j;
                }
                _map[tmp]++;
            }
        }
        int ans = 0;
        for(map<int ,int>::iterator iter = _map.begin(); iter!=_map.end(); iter++){
            ans += iter->second;
            if(ans>=k){
                ans = iter->first;
                break;
            }
        }
        cout<<ans<<endl;
        return ans;
    }
};

int main(){
    int m, n, k;
    map<int, int>_m;
    cin>>m>>n>>k;
    Solution s;
    s.findKthNumber(m, n, k);
    return 0;
}


四、Bs 的Ac 代码:

#include<iostream>
#include <map>
using namespace std;

#define MaxLen 30010
class Solution {
public:
    //获取不大于k 的节点的个数
    int getSmallerNum(int m, int n, int value){
        int ans = 0;
        for(int i=1; i<=m; i++){
            ans += min(n, value/i);
        }
        return ans;
    }
    int findKthNumber(int m, int n, int k) {
        if(k==m*n) return k;
        int left = 1, right = m*n;
        int ans = 0;
        while(left<=right){
            int mid = (right-left)/2 + left;
            int num = getSmallerNum(m, n, mid);
            if(num>=k){
                ans = mid;
                right = right-1;
            }else{
                left = left+1;
            }
        }
        cout<<ans<<endl;
        return ans;
    }
};

int main(){
    int m, n, k;
    cin>>m>>n>>k;
    Solution s;
    s.findKthNumber(m, n, k);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值