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:

  1. The m and n will be in the range [1, 30000].
  2. The k will be in the range [1, m * n]

这道题跟之前那道Kth Smallest Element in a Sorted Matrix没有什么太大的区别,这里的乘法表也是各行各列分别有序的。那么之前帖子里的方法都可以拿来参考。之前帖子中的解法一在这道题中无法通过OJ,维护一个大小为k的优先队列实在是没有利用到这道题乘法表的特点,但是后两种解法都是可以的。为了快速定位出第K小的数字,我们采用二分搜索法,由于是有序矩阵,那么左上角的数字一定是最小的,而右下角的数字一定是最大的,所以这个是我们搜索的范围,然后我们算出中间数字mid,由于矩阵中不同行之间的元素并不是严格有序的,所以我们要在每一行都查找一下mid,由于乘法表每行都是连续数字1,2,3...乘以当前行号(从1开始计数),所以我们甚至不需要在每行中使用二分查找,而是直接定位出位置。具体做法是,先比较mid和该行最后一个数字的大小,最后一数字是n * i,i是行数,n是该行数字的个数,如果mid大的话,直接将该行所有数字的个数加入cnt,否则的话加上mid / i,比如当前行是2, 4, 6, 8, 10,如果我们要查找小于7的个数,那么就是7除以2,得3,就是有三个数小于7,直接加入cnt即可。这样我们就可以快速算出矩阵中所有小于mid的个数,根据cnt和k的大小关系,来更新我们的范围,循环推出后,left就是第K小的数字,参见代码如下:

解法一:

 class Solution {
public:
int findKthNumber(int m, int n, int k) {
int left = , right = m * n;
while (left < right) {
int mid = left + (right - left) / , cnt = ;
for (int i = ; i <= m; ++i) {
cnt += (mid > n * i) ? n : (mid / i);
}
if (cnt < k) left = mid + ;
else right = mid;
}
return right;
}
};

下面这种解法在统计小于mid的数字个数的方法上有些不同,并不是逐行来统计,而是从左下角的数字开始统计,如果该数字小于mid,说明该数字及上方所有数字都小于mid,cnt加上i个,然后向右移动一位继续比较。如果当前数字小于mid了,那么向上移动一位,直到横纵方向有一个越界停止,其他部分都和上面的解法相同,参见代码如下:

解法二:

 class Solution {
public:
int findKthNumber(int m, int n, int k) {
int left = , right = m * n;
while (left < right) {
int mid = left + (right - left) / , cnt = , i = m, j = ;
while (i >= && j <= n) {
if (i * j <= mid) {
cnt += i;
++j;
} else {
--i;
}
}
if (cnt < k) left = mid + ;
else right = mid;
}
return right;
}
};

下面这种解法由网友bambu提供,是对解法二的优化,再快一点,使用除法来快速定位新的j值,然后迅速算出当前行的小于mid的数的个数,然后快速更新i的值,这比之前那种一次只加1或减1的方法要高效许多,感觉像是解法一和解法二的混合体,参见代码如下:

解法三:

 class Solution {
public:
int findKthNumber(int m, int n, int k) {
int left = , right = m * n;
while (left < right) {
int mid = left + (right - left) / , cnt = , i = m, j = ;
while (i >= && j <= n) {
int t = j;
j = (mid > n * i) ? n + : (mid / i + );
cnt += (j - t) * i;
i = mid / j;
}
if (cnt < k) left = mid + ;
else right = mid;
}
return right;
}
};

类似题目:

Kth Smallest Element in a Sorted Matrix

Find K-th Smallest Pair Distance

参考资料:

https://discuss.leetcode.com/topic/101194/my-8-lines-c-solution

https://discuss.leetcode.com/topic/101132/java-solution-binary-search

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Kth Smallest Number in Multiplication Table 乘法表中的第K小的数字的更多相关文章

  1. LeetCode hard 668. Kth Smallest Number in Multiplication Table(二分答案,一次过了,好开心,哈哈哈哈)

    题目:https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/description/ 668. Kth S ...

  2. 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 ...

  3. LeetCode:乘法表中的第K小的数【668】

    LeetCode:乘法表中的第K小的数[668] 题目描述 几乎每一个人都用 乘法表.但是你能在乘法表中快速找到第k小的数字吗? 给定高度m .宽度n 的一张 m * n的乘法表,以及正整数k,你需要 ...

  4. [Swift]LeetCode668. 乘法表中第k小的数 | Kth Smallest Number in Multiplication Table

    Nearly every one have used the Multiplication Table. But could you find out the k-th smallest number ...

  5. 【leetcode】668. Kth Smallest Number in Multiplication Table

    题目如下: 解题思路:几乎和[leetcode]719. Find K-th Smallest Pair Distance 的方法一样.只不过一个是减法一个是乘法,还有一点区别是[leetcode]7 ...

  6. 230. Kth Smallest Element in a BST 找到bst中的第k小的元素

    [抄题]: Given a binary search tree, write a function kthSmallest to find the kth smallest element in i ...

  7. [LintCode] Kth Smallest Number in Sorted Matrix 有序矩阵中第K小的数字

    Find the kth smallest number in at row and column sorted matrix. Have you met this question in a rea ...

  8. 230 Kth Smallest Element in a BST 二叉搜索树中第K小的元素

    给定一个二叉搜索树,编写一个函数kthSmallest来查找其中第k个最小的元素. 注意:你可以假设k总是有效的,1≤ k ≤二叉搜索树元素个数. 进阶:如果经常修改二叉搜索树(插入/删除操作)并且你 ...

  9. 【LeetCode】1415. 长度为 n 的开心字符串中字典序第 k 小的字符串 The k-th Lexicographical String of All Happy Strings of Le

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 日期 题目地址:https://leetcod ...

随机推荐

  1. java开源安全框架-------Apache Shiro--第一天

    1.1.简介 Apache Shiro 是Java的一个安全框架.目前使用Apache Shiro 的人越来越多,因为它相当简单,对比Spring Security,可能没有没有Spring Secu ...

  2. 中文分词 sphni与scws

    1.安装sphnixcd /usr/local/srcwget http://sphinxsearch.com/files/sphinx-2.2.11-release.tar.gztar -zxvf ...

  3. 微信公众号报错 config:invalid signature

    官方已经提供了微信 JS 接口签名校验工具(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign),填入相应的参数就能出来相应的signa ...

  4. Hibernate——配置并访问数据库

    Hibernate,对于java来说很重要的一个东西,用于持久层.之前看了很多配置的,都不行,自己来写一个配置成功的. 环境:jdk1.8,eclipse-jee-oxygen,mysql-conne ...

  5. 第七周PTA作业

    第一题: #include<stdio.h> int main() { ; ; ){ sum=sum+i; i++; } printf("sum = %d\n",sum ...

  6. 2017-2018-1 Java演绎法 第一周 作业

    团队学习:<构建之法> [团队成员]: 学号 姓名 负责工作 20162315 马军 日常统计,项目部分代码 20162316 刘诚昊 项目部分代码,代码质量测试 20162317 袁逸灏 ...

  7. Linux下进程间通信--共享内存:最快的进程间通信方式

    共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...

  8. Beta冲刺Day7

    项目进展 李明皇 今天解决的进度 部分数据传递和使用逻辑测试 林翔 今天解决的进度 服务器端查看个人发布的action,修改已发布消息状态的action,仍在尝试使用第三方云存储功能保存图片 孙敏铭 ...

  9. AWS EC2服务器的HTTPS负载均衡器配置过程

    AWS EC2服务器配置负载均衡器步骤:   1.普通负载均衡器   至少两台EC2实例,这里以Centos6.7系统为例 启动之后先安装个apache的httpd服务器默认80端口,或者使用其他服务 ...

  10. html{font-size:62.5%}

    为什么要使用html,body{font-size:62.5%}? 使用以下代码查看浏览器的初始font-size: <!DOCTYPE html><html><head ...