Kth Smallest Number in Multiplication Table

2 篇文章 0 订阅

# 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]

Solution 1

Firstly, use a map to store different numbers and their occurrences in the multiplication table, then get the Kth smallest number from the map (Time Limit Exceeded)

    // C++
    int findKthNumber(int m, int n, int k) {
        if (m == 0 || n == 0 || k > m * n) {
            return -1;
        }

        unordered_map<int, int> numDict;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                int curNum = i * j;
                if (numDict.count(curNum) <= 0) {
                    numDict[curNum] = 0;
                }
                ++numDict[curNum];
            }
        }

        int count = 0;
        // The Kth smallest number must be less than or equal to k
        for (int i = 1; i <= k; ++i)
        {
            count += numDict[i];
            if (count >= k) {
                return i;
            }
        }
    }

Time Complexity: O(m*n + k)
Space Complexity: O(m*n)

Solution 2

Refer to
[1] http://www.cnblogs.com/shuashuashua/p/7500858.html
[2] http://blog.csdn.net/xiaocong1990/article/details/77651714

We can enumerate every number from 1 to m*n, count the number of numbers less than or equal to this number, return the first number with k numbers less than or equal to it.

Inspired by “Basic idea could be same as the Kth smallest number in sorted matrix” from [1]. We can use binary search to reduce the time complexity (not necessary to enumerate every number).

such as m = n = 3, k = 5
1 2 3
2 4 6
3 6 9

start = 1, end = m * n, mid = start + (end - start)
if count(less than or equal to mid) < k: start = mid + 1 (the Kth smallest number can’t be in range [start, mid])
if count(less than or equal to mid) >= k: end = mid (the Kth smallest number must be in range [start, mid])
repeat this process, until start = end, that is, find the kth smallest number

Another problem: how to compute count(less than or equal to mid) ?
mid divides i=1…m, represent the number less than or equal to mid in row i. Of course, the number must be less than or equal to n, so

count(less than or equal to mid) += (mid / i >= n) ? n : mid / i, i = 1…m

    // C++
    int findKthNumber(int m, int n, int k) {
        if (m <= 0 || n <= 0 || k > m * n) {
            return -1;
        }

        int start = 1;
        int end = m * n;
        while (start < end) {
            int mid = start + (end - start) / 2;
            // count all nums less than or equal to mid
            int cnt = 0;
            for (int i = 1; i <= m; ++i) {
                cnt += (mid / i >= n) ? n : mid / i;
            }
            if (cnt < k) {
                start = mid + 1;
            } else {
                end = mid;
            }
        }
        return start;
    }

   """ python """
   def findKthNumber(self, m, n, k):
       """
       :type m: int
       :type n: int
       :type k: int
       :rtype: int
       """  
       if m <= 0 or n <= 0 or k > m * n:
           return -1

       start = 1
       end = m * n
       while start < end:
           mid = start + (end - start) // 2
           cnt = 0
           for i in range(1, m + 1):
               max_cnt = mid // i
               if max_cnt <= n:
                   cnt += max_cnt
               else:
                   cnt += n
           if cnt < k:
               start = mid + 1
           """ this condition is wrong
           Because if a count (less than or equal to mid) > k, it still maybe the Kth smallest number (such as 1 2 3; 2 4 6, 3 is the 4th smallest number, but count(<=3) = 5 > 4)
           """
           # elif cnt > k:
           #    end = mid - 1
           else:
               end = mid
       return start

Time Complexity: O(m*log(m*n))
Space Complexity: O(1)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值