zoukankan      html  css  js  c++  java
  • 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:

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

    解题思路:

    我一看这题,跟另外一道题有点类似啊(378. Kth Smallest Element in a Sorted Matrix),当时喜滋滋的就开始做。

    利用了矩阵本身的性质(每一行每一列都有序,但是列与列,行与行并没有很有序)并且与priority_queue(重写比较器使之成为最小堆)结合使用。

    给的例子都过了,然后我喜滋滋的点了submit :)

    没过。

    leetcode怎么会有一毛一样的题呢?naive :)

    乘法表比起有序矩阵来说,性质更加特殊:每一行都是一个等差数列。

    我们可以使用binary search二分搜索来解答。

    左边界为1;右边界为 m*n

    算得中间值,然后来看比中间值小的数字在乘法表里有多少?

    多于k的话,将右边界左移。

    小于k的话,将左边界右移。

    参考了GrandYang(不用看就能写对了已经,大佬就是我的答案) 的解法。

    重点理解算比中间值小的数字的个数的过程:

    • 将mid 于 i*n比较, i是行数,i  belongs to [1, m], i*n是本行最大的数字
      • 若mid > i*n 说明 mid 比这一行都大,cnt(计数器) += n
      • 若mid <= i*n 说明mid 处于这一行中。cnt += mid / i, 因为i是一个因数,在这一行内分别于1.... n 相乘,所以可以通过这种方式计算 子这一行里小于mid的个数。

    这道题告诉我:

    1. 遇到类似原题不要太开心,要把它当新题做。
    2. 要仔细分析输入的性质并且加以利用。
    3. 人生真的好难

    代码:

    class Solution {
    public:
        int findKthNumber(int m, int n, int k) {
            int l = 1, r = m*n;
            while(l < r){
                int mid = l/2 + r/2;
                //calculate current number of element less than mid position;
                int cnt = 0;
                for(int i = 1; i <= m; ++i){
                    cnt += (mid > n*i) ? n : mid/i; 
                }
                if (cnt < k) l = mid + 1;
                else r = mid;
            }
            return r;
        }
    };

    时间复杂度 O(log n), 空间O(1)

  • 相关阅读:
    数据持久化的复习
    iOS: 消息通信中的Notification&KVO
    iOS 证书与签名 解惑详解
    数据持久化 技术比较
    iOS开发拓展篇-XMPP简单介绍
    iOS block并发
    Xcode把应用程序打包成ipa
    谈谈用SQLite和FMDB而不用Core Data
    cannot use the same dataset for report.dataset and page.dataset
    cxGRID中的字段怎么能以0.00的格式显示
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/11633336.html
Copyright © 2011-2022 走看看