通用方法:
快排/优先队列
多路归并:使用[哈希表]和优先队列找到K个最小的数即可!
二分:二分目标值统计小于等于该值的元素个数,正好为K个时返回其中最大的元素。
786. 第 K 个最小的素数分数
给你一个按递增顺序排序的数组 arr 和一个整数 k 。数组 arr 由 1 和若干 素数 组成,且其中所有整数互不相同。
对于每对满足 0 < i < j < arr.length 的 i 和 j ,可以得到分数 arr[i] / arr[j] 。
那么第 k 个最小的分数是多少呢? 以长度为 2 的整数数组返回你的答案, 这里 answer[0] == arr[i] 且 answer[1] == arr[j] 。
示例 1:
输入:arr = [1,2,3,5], k = 3 输出:[2,5] 解释:已构造好的分数,排序后如下所示: 1/5, 1/3, 2/5, 1/2, 3/5, 2/3 很明显第三个最小的分数是 2/5
示例 2:
输入:arr = [1,7], k = 1 输出:[1,7]
提示:
2 <= arr.length <= 10001 <= arr[i] <= 3 * 104arr[0] == 1arr[i]是一个 素数 ,i > 0arr中的所有数字 互不相同 ,且按 严格递增 排序1 <= k <= arr.length * (arr.length - 1) / 2
思路:
方法一:多路归并
使用优先队列找到K个最小的数,返回第K个最小的数
方法二:二分
二分答案X,找到小于等于X的所有元素,恰为K个时返回其中最大的一个即可。
// 多路归并class Solution {public int[] kthSmallestPrimeFraction(int[] arr, int k) {PriorityQueue<int[]> q = new PriorityQueue<>((o1, o2) -> (arr[o1[0]] * arr[o2[1]] - arr[o2[0]] * arr[o1[1]]));for (int i = 1; i < arr.length; i++)q.offer(new int[]{0, i});int[] res = new int[2];while (k-- > 0) {// System.out.println(q);int[] p = q.poll();res[0] = arr[p[0]];res[1] = arr[p[1]];if (p[0] + 1 < p[1])q.offer(new int[]{p[0] + 1, p[1]});}return res;}}
// 二分class Solution {public int[] kthSmallestPrimeFraction(int[] arr, int k) {double l = 0, r = 1.0;int x = 0, y = 1;while (true) {double mid = (l + r) / 2;int cnt = 0;x = 0;y = 1;for (int j = -1, i = 1; i < arr.length; i++) {while (1.0 * arr[j + 1] / arr[i] < mid) {j++;if (x * arr[i] < y * arr[j]) {x = arr[j];y = arr[i];}}cnt += j + 1;}if (cnt == k)return new int[]{x, y};if (cnt < k)l = mid;elser = mid;}}}
440. 字典序的第K小数字
给定整数 n 和 k,返回 [1, n] 中字典序第 k 小的数字。
示例 1:
输入: n = 13, k = 2 输出: 10 解释: 字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。
示例 2:
输入: n = 1, k = 1 输出: 1
提示:
- 1 <= k <= n <= 109
思路:
数位统计问题
考虑前缀出现的次数,从前往后确定每一位
class Solution {public int findKthNumber(int n, int k) {int prefix = 1;while (k > 1) {int cnt = find(prefix, n);if (cnt >= k) {prefix *= 10;k--;} else {prefix++;k -= cnt;}}return prefix;}int find(int prefix, int n) {String s = String.valueOf(n), t = String.valueOf(prefix);long p = 1;int len = s.length() - t.length();long res = 0;for (int i = 0; i < len; i++) {res += p;p *= 10;}s = s.substring(0, t.length());if (s.compareTo(t) > 0) {res += p;} else if (s.compareTo(t) == 0) {res += n - prefix * p + 1;}return (int)(res);}}
215. 数组中的第K个最大元素
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2 输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4
提示:
- 1 <= k <= nums.length <= 104
- -104 <= nums[i] <= 104
思路:
优先队列/快速排序
// 优先队列class Solution {public int findKthLargest(int[] nums, int k) {PriorityQueue<Integer> q = new PriorityQueue<>();for (int x : nums) {q.offer(x);if (q.size() > k)q.poll();}return q.poll();}}// 快速排序class Solution {public int findKthLargest(int[] nums, int k) {int n = nums.length;return quickSort(nums, 0, n - 1, k - 1);}int quickSort(int[] nums, int l, int r, int k) {if (l == r)return nums[l];int x = nums[l + r >> 1];int i = l - 1, j = r + 1;while (i < j) {while (nums[++i] > x);while (nums[--j] < x);if (i < j) {int t = nums[i];nums[i] = nums[j];nums[j] = t;}}if (j >= k)return quickSort(nums, l, j, k);elsereturn quickSort(nums, j + 1, r, k);}}
面试题 17.14. 最小K个数
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4 输出: [1,2,3,4]
提示:
- 0 <= len(arr) <= 100000
- 0 <= k <= min(100000, len(arr))
思路:
快排/优先队列
// 优先队列class Solution {public int[] smallestK(int[] arr, int k) {PriorityQueue<Integer> q = new PriorityQueue<>((o1, o2) -> o2.compareTo(o1));for (int x : arr) {q.offer(x);if (q.size() > k)q.poll();}int[] res = new int[k];for (int i = k - 1; i >= 0; i--)res[i] = q.poll();return res;}}// 快排class Solution {public int[] smallestK(int[] arr, int k) {int n = arr.length;quickSort(arr, 0, n - 1, k - 1);int[] res = new int[k];for (int i = 0; i < k; i++)res[i] = arr[i];return res;}void quickSort(int[] q, int l, int r, int k) {if (l >= r)return;int x = q[l + r >> 1], i = l - 1, j = r + 1;while (i < j) {while (q[++i] < x);while (q[--j] > x);if (i < j) {q[i] ^= q[j];q[j] ^= q[i];q[i] ^= q[j];}}if (k <= j)quickSort(q, l, j, k);elsequickSort(q, j + 1, r, k);}}
