目录

堆结构和堆排序
import java.util.Arrays;
public class MyMaxHeap {
private int[] heap;
private final int limit;
private int heapSize;
public MyMaxHeap(int limit) {
this.limit = limit;
heap = new int[limit];
heapSize = 0;
}
public boolean isEmpty() {
return heapSize == 0;
}
public boolean isFull() {
return heapSize == limit;
}
public void push(int value) {
if (heapSize == limit) {
throw new RuntimeException("heap is full");
}
heap[heapSize] = value;
heapInsert(heap, heapSize++);
}
public int pop() {
int ans = heap[0];
swap(heap, 0, --heapSize);
heapify(heap, 0, heapSize);
return ans;
}
private void heapInsert(int[] arr, int index) {
//当arr[index]不比arr[index父]大了,或者index来到0位置了
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
//从index位置,往下看,不断的下沉
private void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 1;
while (left < heapSize) {
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
}
private void swap(int[] arr, int l, int r) {
int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
//从小到大进行排序
public void heapSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// O(N*log(N))
// for (int i = 0; i < arr.length; i++) {
// heapInsert(arr, i);
// }
// O(N)
for (int i = arr.length - 1; i >= 0; i--) {
heapify(arr, i, arr.length);
}
int size = arr.length;
swap(arr, 0, --size);
// O(N*logN)
while (size > 0) {
heapify(arr, 0, size);
swap(arr, 0, --size);
}
}
public static void main(String[] args) {
int arr[] = {3, 6, 4, 8, 4, 8, 4, 9, 4, 76, 2, 5, 1};
MyMaxHeap heap = new MyMaxHeap(arr.length);
for (int i = 0; i < arr.length; i++) {
heap.push(arr[i]);
}
for (int i = 0; i < arr.length; i++) {
int val = heap.pop();
System.out.print(val + " ");
}
System.out.println();
heap.heapSort(arr);
System.out.println(Arrays.toString(arr));
}
}
215. 数组中的第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
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> heap = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
for (int num : nums) {
heap.add(num);
}
int num = nums[0];
for (int i = 0; i < k; i++) {
num = heap.poll();
}
return num;
}
解析:建立一个大顶堆
弹出k个元素即可
第k个元素即为求的答案
264. 丑数 II 中等
编写一个程序,找出第 n
个丑数。
丑数就是质因数只包含 2, 3, 5
的正整数。
示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
是前 10 个丑数。
说明:
1
是丑数。n
不超过1690。
class Solution {
//数组+堆+set
private int[] nums = new int[1690];
public Solution() {
Set<Long> set = new HashSet<>();
PriorityQueue<Long> minHeap = new PriorityQueue<>();
set.add(1L);
minHeap.add(1L);
int[] ugly = new int[]{2, 3, 5};
long curr, temp;
for (int i = 0; i < 1690; i++) {
curr = minHeap.poll();
nums[i] = (int) curr;
for (int j : ugly) {
temp = j * curr;
if (!set.contains(temp)) {
set.add(temp);
minHeap.add(temp);
}
}
}
}
public int nthUglyNumber(int n) {
return nums[n - 1];
}
}
解析:生成一个全局数组,预计算1679个元素
使用一个set,用于去重,使用一个堆,每次弹出最小的元素放入数组中
返回数组第n-1个即可
//个人实现 不用预生成数组
Set<Long> set = new HashSet<>();
PriorityQueue<Long> minHeap = new PriorityQueue<>();
private int res;
public int nthUglyNumber(int n) {
int[] ugly = new int[]{2, 3, 5};
set.add(1L);
minHeap.add(1L);
long curr, temp;
for (int i = 0; i < n; i++) {
curr = minHeap.poll();
res = (int) curr;
for (int j : ugly) {
temp = j * curr;
if (!set.contains(temp)) {
set.add(temp);
minHeap.add(temp);
}
}
}
return res;
}
解析:不用预生成数组,用一个变量代替
//动态规划
public int nthUglyNumber(int n) {
int ugly, i2 = 0, i3 = 0, i5 = 0;
int[] nums = new int[n];
nums[0] = 1;
for (int i = 1; i < n; i++) {
ugly = Math.min(nums[i2] * 2, Math.min(nums[i3] * 3, nums[i5] * 5));
nums[i] = ugly;
if (ugly == nums[i2] * 2) {
i2++;
}
if (ugly == nums[i3] * 3) {
i3++;
}
if (ugly == nums[i5] * 5) {
i5++;
}
}
return nums[n - 1];
}
解析:每次选出最小的值赋值给数组
313. 超级丑数 中等
编写一段程序来查找第 n
个超级丑数。
超级丑数是指其所有质因数都是长度为 k
的质数列表 primes
中的正整数。
示例:
输入: n = 12,primes
=[2,7,13,19]
输出: 32 解释: 给定长度为 4 的质数列表 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。
说明:
1
是任何给定primes
的超级丑数。- 给定
primes
中的数字以升序排列。 - 0 <
k
≤ 100, 0 <n
≤ 106, 0 <primes[i]
< 1000 。 - 第
n
个超级丑数确保在 32 位有符整数范围内。
//个人实现 堆+set
private Set<Long> set = new HashSet<>();
private PriorityQueue<Long> minHeap = new PriorityQueue<>();
private int res;
public int nthSuperUglyNumber(int n, int[] primes) {
set.add(1L);
minHeap.add(1L);
long curr, temp;
for (int i = 0; i < n; i++) {
curr = minHeap.poll();
res = (int) curr;
for (int prime : primes) {
temp = prime * curr;
if (!set.contains(temp)) {
set.add(temp);
minHeap.add(temp);
}
}
}
return res;
}
解析:和264丑数解法相同
347. 前 K 个高频元素 中等
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
- 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
- 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
- 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
- 你可以按任意顺序返回答案。
//堆 个人实现
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
PriorityQueue<Map.Entry<Integer, Integer>> maxHeap = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
maxHeap.add(entry);
}
int res[] = new int[k];
for (int i = 0; i < k && maxHeap.size() > 0; i++) {
res[i] = maxHeap.poll().getKey();
}
return res;
}
解析:map+堆
373. 查找和最小的K对数字 中等
给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。
定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。
找到和最小的 k 对数字 (u1,v1), (u2,v2) ... (uk,vk)。
示例 1:
输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
输出: [1,2],[1,4],[1,6]
解释: 返回序列中的前 3 对数:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
示例 2:
输入: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
输出: [1,1],[1,1]
解释: 返回序列中的前 2 对数:
[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
示例 3:
输入: nums1 = [1,2], nums2 = [3], k = 3
输出: [1,3],[2,3]
解释: 也可能序列中所有的数对都被返回:[1,3],[2,3]
//堆 个人实现,效率低
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
PriorityQueue<List<Integer>> minHeap = new PriorityQueue<>(new Comparator<List<Integer>>() {
@Override
public int compare(List<Integer> o1, List<Integer> o2) {
int num1 = o1.get(0) + o1.get(1);
int num2 = o2.get(0) + o2.get(1);
return Integer.compare(num1, num2);
}
});
List<List<Integer>> res = new ArrayList<>();
for (int num1 : nums1) {
for (int num2 : nums2) {
List<Integer> list = new ArrayList<>();
list.add(num1);
list.add(num2);
minHeap.add(list);
}
}
for (int i = 0; i < k && minHeap.size() > 0; i++) {
res.add(minHeap.poll());
}
return res;
}
解析:将相加的结果存入小顶堆中
遍历查找第k个即可
378. 有序矩阵中第K小的元素 中等
给定一个 n x n
矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k
小的元素。
请注意,它是排序后的第 k
小元素,而不是第 k
个不同的元素。
示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。
提示:
你可以假设 k 的值永远是有效的,1 ≤ k ≤ n2
。
//堆 个人实现,效率较低
public int kthSmallest(int[][] matrix, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
minHeap.add(matrix[i][j]);
}
}
int res = matrix[0][0];
for (int i = 0; i < k; i++) {
res = minHeap.poll();
}
return res;
}
解析:使用一个小顶堆将元素全部存储起来,找第k个即可
451. 根据字符出现频率排序 中等
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
示例 1:
输入:
"tree"
输出:
"eert"
解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
示例 2:
输入:
"cccaaa"
输出:
"cccaaa"
解释:
'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。
示例 3:
输入:
"Aabb"
输出:
"bbAa"
解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。
//堆 个人实现,效率较低
Map<Character, Integer> map = new HashMap<>();
public String frequencySort(String s) {
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
PriorityQueue<Map.Entry<Character, Integer>> heap = new PriorityQueue<>(new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
heap.add(entry);
}
StringBuilder builder = new StringBuilder();
while (!heap.isEmpty()) {
Map.Entry<Character, Integer> entry = heap.poll();
for (int i = 0; i < entry.getValue(); i++) {
builder.append(entry.getKey());
}
}
return builder.toString();
}
解析:使用map来存储每个字符及其出现的次数
将map放入一个大顶堆中
遍历放入builder中
返回即可
//map+list排序实现
private Map<Character, Integer> map = new HashMap<>();
public String frequencySort(String s) {
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
StringBuilder builder = new StringBuilder();
for (Map.Entry<Character, Integer> entry : list) {
for (int i = 0; i < entry.getValue(); i++) {
builder.append(entry.getKey());
}
}
return builder.toString();
}
解析:使用map将字符及其数量存储起来
放入集合list中进行排序
遍历即可
692. 前K个高频单词 中等
给一非空的单词列表,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。
示例 1:
输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
注意,按字母顺序 "i" 在 "love" 之前。
示例 2:
输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,
出现次数依次为 4, 3, 2 和 1 次。
注意:
- 假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。
- 输入的单词均由小写字母组成。
扩展练习:
- 尝试以 O(n log k) 时间复杂度和 O(n) 空间复杂度解决。
//个人实现 堆+map
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> map = new HashMap<>();
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
PriorityQueue<Map.Entry<String, Integer>> maxHeap = new PriorityQueue<>(new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
if (o1.getValue() != o2.getValue()) {
return o2.getValue().compareTo(o1.getValue());
} else {
return o1.getKey().compareTo(o2.getKey());
}
}
});
for (Map.Entry<String, Integer> entry : map.entrySet()) {
maxHeap.add(entry);
}
List<String> list = new ArrayList<>();
for (int i = 0; i < k && maxHeap.size() > 0; i++) {
list.add(maxHeap.poll().getKey());
}
return list;
}
解析:使用堆+map实现
767. 重构字符串 中等
给定一个字符串S
,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab"
输出: "aba"
示例 2:
输入: S = "aaab"
输出: ""
注意:
S
只包含小写字母并且长度在[1, 500]
区间内。
public String reorganizeString(String S) {
int n = S.length();
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < S.length(); i++) {
char ch = S.charAt(i);
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(new Comparator<Map.Entry<Character, Integer>>() {
//从小到大排序
@Override
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
if (o1.getValue() != o2.getValue()) {
return o1.getValue().compareTo(o2.getValue());
} else {
return o1.getKey().compareTo(o2.getKey());
}
}
});
int t = 1;
char[] chars = new char[n];
for (Map.Entry<Character, Integer> entry : list) {
if (entry.getValue() > (n + 1) / 2) {
return "";
}
for (int i = 0; i < entry.getValue(); i++) {
if (t >= n) {
t = 0;
}
chars[t] = entry.getKey();
t += 2;
}
}
return String.valueOf(chars);
}
解析:使用map将各个字符及其数量存储起来
隔空插入字符
class Solution {
//map+堆+新类
public String reorganizeString(String S) {
int n = S.length();
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
char ch = S.charAt(i);
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
PriorityQueue<MuitChar> maxHeap = new PriorityQueue<>(new Comparator<MuitChar>() {
@Override
public int compare(MuitChar o1, MuitChar o2) {
if (o1.count != o2.count) {
return o2.count - o1.count;
} else {
return o1.letter - o2.letter;
}
}
});
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
if (entry.getValue() > (n + 1) / 2) {
return "";
}
maxHeap.add(new MuitChar(entry.getKey(), entry.getValue()));
}
StringBuilder builder = new StringBuilder();
while (maxHeap.size() >= 2) {
MuitChar muitChar1 = maxHeap.poll();
MuitChar muitChar2 = maxHeap.poll();
builder.append(muitChar1.letter);
builder.append(muitChar2.letter);
if (--muitChar1.count > 0) {
maxHeap.add(muitChar1);
}
if (--muitChar2.count > 0) {
maxHeap.add(muitChar2);
}
}
if (maxHeap.size() > 0) {
builder.append(maxHeap.poll().letter);
}
return builder.toString();
}
}
class MuitChar{
char letter;
int count;
public MuitChar(char letter, int count) {
this.letter = letter;
this.count = count;
}
}
解析:先用一个map放入字符串及其数量
将map中的结果封装为MuitChar放入大顶堆中
每次取出堆中两个元素放入builder中
//个人实现 map+堆
public String reorganizeString(String S) {
Map<Character, Integer> map = new HashMap<>();
int n = S.length();
for (int i = 0; i < n; i++) {
char ch = S.charAt(i);
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
PriorityQueue<Map.Entry<Character, Integer>> maxHeap = new PriorityQueue<>(new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
if (o1.getValue() != o2.getValue()) {
return o2.getValue().compareTo(o1.getValue());
} else {
return o1.getKey().compareTo(o2.getKey());
}
}
});
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
if (entry.getValue() > (n + 1) / 2) {
return "";
}
maxHeap.add(entry);
}
StringBuilder builder = new StringBuilder();
while (maxHeap.size() >= 2) {
Map.Entry<Character, Integer> entry1 = maxHeap.poll();
Map.Entry<Character, Integer> entry2 = maxHeap.poll();
builder.append(entry1.getKey());
builder.append(entry2.getKey());
if (entry1.getValue() - 1 > 0) {
entry1.setValue(entry1.getValue() - 1);
maxHeap.add(entry1);
}
if (entry2.getValue() - 1 > 0) {
entry2.setValue(entry2.getValue() - 1);
maxHeap.add(entry2);
}
}
if (maxHeap.size() > 0) {
builder.append(maxHeap.poll().getKey());
}
return builder.toString();
}
解析:每次pop出两个元素
973. 最接近原点的 K 个点 中等
我们有一个由平面上的点组成的列表 points
。需要从中找出 K
个距离原点 (0, 0)
最近的点。
(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。
示例 1:
输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释:
(1, 3) 和原点之间的距离为 sqrt(10),
(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。
示例 2:
输入:points = [[3,3],[5,-1],[-2,4]], K = 2
输出:[[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)
提示:
1 <= K <= points.length <= 10000
-10000 < points[i][0] < 10000
-10000 < points[i][1] < 10000
//个人实现 堆
public int[][] kClosest(int[][] points, int K) {
int[][] res = new int[K][2];
PriorityQueue<int[]> minHeap = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
int num1 = o1[0] * o1[0] + o1[1] * o1[1];
int num2 = o2[0] * o2[0] + o2[1] * o2[1];
return Integer.compare(num1, num2);
}
});
for (int i = 0; i < points.length; i++) {
minHeap.add(points[i]);
}
for (int i = 0; i < K && minHeap.size() > 0; i++) {
res[i] = minHeap.poll();
}
return res;
}
解析:使用一个小顶堆,将每一个数组放入小顶堆中,从中选出K个数组
1054. 距离相等的条形码 中等
在一个仓库里,有一排条形码,其中第 i
个条形码为 barcodes[i]
。
请你重新排列这些条形码,使其中两个相邻的条形码 不能 相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:[1,1,1,2,2,2]
输出:[2,1,2,1,2,1]
示例 2:
输入:[1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]
提示:
1 <= barcodes.length <= 10000
1 <= barcodes[i] <= 10000
//大顶堆+map
public int[] rearrangeBarcodes(int[] barcodes) {
Map<Integer, Integer> map = new HashMap<>();
int n = barcodes.length;
for (int barcode : barcodes) {
map.put(barcode, map.getOrDefault(barcode, 0) + 1);
}
PriorityQueue<Map.Entry<Integer, Integer>> maxHeap = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
if (o1.getValue() != o2.getValue()) {
return o2.getValue().compareTo(o1.getValue());
} else {
return o1.getKey().compareTo(o2.getKey());
}
}
});
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue() > (n + 1) / 2) {
return new int[]{};
}
maxHeap.add(entry);
}
int res[] = new int[n];
int t = 0;
while (maxHeap.size() >= 2) {
Map.Entry<Integer, Integer> entry1 = maxHeap.poll();
Map.Entry<Integer, Integer> entry2 = maxHeap.poll();
res[t++] = entry1.getKey();
res[t++] = entry2.getKey();
if (entry1.getValue() - 1 > 0) {
entry1.setValue(entry1.getValue() - 1);
maxHeap.add(entry1);
}
if (entry2.getValue() - 1 > 0) {
entry2.setValue(entry2.getValue() - 1);
maxHeap.add(entry2);
}
}
if (maxHeap.size() > 0) {
res[t++] = maxHeap.poll().getKey();
}
return res;
}
解析:大顶堆+map
面试题
面试题 17.09. 第 k 个数 中等
有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
示例 1:
输入: k = 5
输出: 9
public int getKthMagicNumber(int k) {
int res = 0;
Set<Long> set = new HashSet<>();
PriorityQueue<Long> minHeap = new PriorityQueue<>();
set.add(1L);
minHeap.add(1L);
int arr[] = new int[]{3, 5, 7};
long curr, temp;
for (int i = 0; i < k; i++) {
curr = minHeap.poll();
res = (int) curr;
for (int ele : arr) {
temp = ele * curr;
if (!set.contains(temp)) {
set.add(temp);
minHeap.add(temp);
}
}
}
return res;
}
解析:就是丑数的题解
面试题 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))
//个人实现 堆
public int[] smallestK(int[] arr, int k) {
int[] res = new int[k];
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int ele : arr) {
minHeap.add(ele);
}
for (int i = 0; i < k && minHeap.size() > 0; i++) {
res[i] = minHeap.poll();
}
return res;
}
解析:将元素全部存储在堆中,选出前k个元素返回即可