二分查找:求解《668. 乘法表中第k小的数》

2022-05-18 10:48:44
二分查找,求解《668. 乘法表中第k小的数》

例题

668. 乘法表中第k小的数

几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第k小的数字吗?
给定高度m 、宽度n 的一张 m * n的乘法表,以及正整数k,你需要返回表中第k 小的数字。

例 1:
输入: m = 3, n = 3, k = 5
输出: 3
解释:
乘法表:
1 2 3
2 4 6
3 6 9
第5小的数字是 3 (1, 2, 2, 3, 3).

答案

二分查找 + [1, m] 循环

var findKthNumber = function(m, n, k) {
  let l = 0, r = m * n
  while (l < r) {
    const mid = l + r >> 1
    let count = 0
    for (let i = 1; i <= m; i++) count += Math.min(mid / i | 0, n)
    count >= k ? r = mid : l = mid + 1
  }
  return l
};
function findKthNumber(m: number, n: number, k: number): number {
  let l = 0, r = m * n
  while (l < r) {
    const mid = l + r >> 1
    let count = 0
    for (let i = 1; i <= m; i++) count += Math.min(mid / i | 0, n)
    count >= k ? r = mid : l = mid + 1
  }
  return l
};
func findKthNumber(m int, n int, k int) int {
  l, r := 0, m * n
  for l < r {
    mid, count := (l + r) >> 1, 0
    for i := 1; i <= m; i++ {
      count += min(mid / i | 0, n)
    } 
    if count >= k {
      r = mid
    } else {
      l = mid + 1
    }
  }
  return l
}
func min(a int, b int) int {
  if a < b {
    return a
  }
  return b
}
class Solution {
  function findKthNumber($m, $n, $k) {
    $l = 0;
    $r = $m * $n;
    while ($l < $r) {
      $mid = $l + $r >> 1;
      $count = 0;
      for ($i = 1; $i <= $m; $i++) $count += min($mid / $i | 0, $n);
      $count >= $k ? $r = $mid : $l = $mid + 1;
    }
    return $l;
  }
}
class Solution(object):
    def findKthNumber(self, m, n, k):
      l, r = 0, m * n
      while l < r:
        mid = l + r >> 1
        count = 0
        for i in range(1, m + 1):
          count += min(mid / i | 0, n)
        if count >= k: r = mid
        else: l = mid + 1
      return l
class Solution:
    def findKthNumber(self, m: int, n: int, k: int) -> int:
      l, r = 0, m * n
      while l < r:
        mid = l + r >> 1
        count = 0
        for i in range(1, m + 1):
          count += min(mid // i, n)
        if count >= k: r = mid
        else: l = mid + 1
      return l
class Solution {
  public int findKthNumber(int m, int n, int k) {
    int l = 0;
    int r = m * n;
    while (l < r) {
      int mid = l + r >> 1;
      int count = 0;
      for (int i = 1; i <= m; i++) count += Math.min(mid / i | 0, n);
      if (count >= k) r = mid;
      else l = mid + 1;
    }
    return l;
  }
}

二分查找 + [(mid / n | 0) * n + 1, m] 循环

var findKthNumber = function(m, n, k) {
  let l = 0, r = m * n
  while (l < r) {
    const mid = l + r >> 1
    let count = (mid / n | 0) * n
    for (let i = (mid / n | 0) + 1; i <= m; i++) count += mid / i | 0
    count >= k ? r = mid : l = mid + 1
  }
  return l
};
function findKthNumber(m: number, n: number, k: number): number {
  let l = 0, r = m * n
  while (l < r) {
    const mid = l + r >> 1
    let count = (mid / n | 0) * n
    for (let i = (mid / n | 0) + 1; i <= m; i++) count += mid / i | 0
    count >= k ? r = mid : l = mid + 1
  }
  return l
};
func findKthNumber(m int, n int, k int) int {
  l, r := 0, m * n
  for l < r {
    mid := (l + r) >> 1
    count := (mid / n | 0) * n
    for i :=  (mid / n | 0) + 1; i <= m; i++ {
      count += mid / i | 0
    } 
    if count >= k {
      r = mid
    } else {
      l = mid + 1
    }
  }
  return l
}
class Solution {
  function findKthNumber($m, $n, $k) {
    $l = 0;
    $r = $m * $n;
    while ($l < $r) {
      $mid = $l + $r >> 1;
      $count = ($mid / $n | 0) * $n;
      for ($i = ($mid / $n | 0) + 1; $i <= $m; $i++) $count += $mid / $i | 0;
      $count >= $k ? $r = $mid : $l = $mid + 1;
    }
    return $l;
  }
}
class Solution(object):
    def findKthNumber(self, m, n, k):
      l, r = 0, m * n
      while l < r:
        mid = l + r >> 1
        count = (mid / n | 0) * n
        for i in range((mid / n | 0) + 1, m + 1):
          count += mid / i | 0
        if count >= k: r = mid
        else: l = mid + 1
      return l
class Solution:
    def findKthNumber(self, m: int, n: int, k: int) -> int:
      l, r = 0, m * n
      while l < r:
        mid = l + r >> 1
        count = mid // n * n
        for i in range(mid // n + 1, m + 1):
          count += mid // i
        if count >= k: r = mid
        else: l = mid + 1
      return l
class Solution {
  public int findKthNumber(int m, int n, int k) {
    int l = 0;
    int r = m * n;
    while (l < r) {
      int mid = l + r >> 1;
      int count = (mid / n | 0) * n;
      for (int i = (mid / n | 0) + 1; i <= m; i++) count += mid / i | 0;
      if (count >= k) r = mid;
      else l = mid + 1;
    }
    return l;
  }
}


排序,二分查找:求解《436. 寻找右区间》
排序,二分查找(Python 的 bisect.bisect_left 和 Golang 的 sort.Search),求解《436. 寻找右区间》
RabinKarp 哈希算法、二分查找:求解《1044. 最长重复子串》
用 RabinKarp 哈希算法和二分查找,求解《1044. 最长重复子串》