leetcode题解-668. Kth Smallest Number in Multiplication Table

题目:

Nearly every one have used the Multiplication Table. But could you find out the k-th smallest number quickly from the multiplication table?

Given the height m and the length n of a m * n Multiplication Table, and a positive integer k, you need to return the k-th smallest number in this table.

Example 1:
Input: m = 3, n = 3, k = 5
Output: 
Explanation: 
The Multiplication Table:
1   2   3
2   4   6
3   6   9

The 5-th smallest number is 3 (1, 2, 2, 3, 3).
Example 2:
Input: m = 2, n = 3, k = 6
Output: 
Explanation: 
The Multiplication Table:
1   2   3
2   4   6

The 6-th smallest number is 6 (1, 2, 2, 3, 4, 6).
Note:
The m and n will be in the range [1, 30000].
The k will be in the range [1, m * n]

本题就是寻找乘法表中第k小的数,但是这个题目其实跟之前一道求一个行和列都是增序排列的矩阵中找第k小的元素是一样的,不明白为什么这里又放了出来。不过这道题目相对来说更加简单,因为元素排列更加有规律,甚至是一个对角矩阵的形式。我们可以下使用之前一道题目的思路来解决,就是对第一个元素和最后一个元素进行二叉搜索,然后每个元素判断每一行有几个比其小的值并求和,看是否==k即可。代码如下所示:

    public static int findKthNumber(int m, int n, int k) {
        int left=1, right = m*n, mid;
        while(left <= right){
            mid = left + (right-left)/2;
            int count=0, j=n;
            for(int i=1; i<=m; i++){
            //遍历每一行
                //看一行中有几个元素小于当前值
                while(j >= 1 && i*j > mid) j--;
                //求和
                count += j;
            }
            if(count < k)left = mid+1;
            else right = mid - 1;
        }
        return left;
    }

此外,考虑到当前题目的特殊性我们还可以使用下面这个方法来解决,但是效率没有上面好,只可以击败85%的用户:

public int findKthNumber1(int m, int n, int k) {
        int low = 1, high = m * n;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            int count = helper(m, n, mid);
            if (count >= k) high = mid - 1;
            else low = mid + 1;
        }
        return low;
    }
    private int helper(int m, int n, int num) {
        int count = 0;
        for (int i = 1; i <= m; i++) {
            count += Math.min(num / i, n);
        }
        return count;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值