目录
347. 前 K 个高频元素
407. 接雨水 II
方法 1:堆
想法
k = 1
时问题很简单,线性时间内就可以解决。只需要用哈希表维护元素出现频率,每一步更新最高频元素即可。
当 k > 1
就需要一个能够根据出现频率快速获取元素的数据结构,这就是优先队列。
class Solution {
public List topKFrequent(int[] nums, int k) {
//统计频率
HashMap mp = new HashMap();
for (int n: nums) {
mp.put(n, mp.getOrDefault(n, 0) + 1);
}
PriorityQueue heap =
new PriorityQueue((n1, n2) -> mp.get(n1) - mp.get(n2));
for (int n: mp.keySet()) {
heap.add(n);
if (heap.size() > k)
heap.poll();
}
List top_k = new LinkedList();
while (!heap.isEmpty())
top_k.add(heap.poll());
Collections.reverse(top_k);
return top_k;
}
}
class Solution {
public List topKFrequent(int[] nums, int k) {
// 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
HashMap map = new HashMap();
for(int num : nums){
if (map.containsKey(num)) {
map.put(num, map.get(num) + 1);
} else {
map.put(num, 1);
}
}
// 遍历map,用最小堆保存频率最大的k个元素
PriorityQueue pq = new PriorityQueue<>(new Comparator() {
@Override
public int compare(Integer a, Integer b) {
return map.get(a) - map.get(b);
}
});
for (Integer key : map.keySet()) {
if (pq.size() < k) {
pq.add(key);
} else if (map.get(key) > map.get(pq.peek())) {
pq.remove();
pq.add(key);
}
}
// 取出最小堆中的元素
List res = new ArrayList<>();
while (!pq.isEmpty()) {
res.add(pq.remove());
}
Collections.reverse(res);
return res;
}
}
给你一个 m x n
的矩阵,其中的值均为正整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。
示例:
给出如下 3x6 的高度图:
[
[1,4,3,1,3,2],
[3,2,1,3,2,4],
[2,3,3,2,3,1]
]
返回 4
class Solution {
public int trapRainWater(int[][] heights) {
if (heights == null || heights.length == 0) return 0;
int n = heights.length;
int m = heights[0].length;
// 用一个vis数组来标记这个位置有没有被访问过
boolean[][] vis = new boolean[n][m];
// 优先队列中存放三元组 [x,y,h] 坐标和高度
PriorityQueue pq = new PriorityQueue<>((o1, o2) -> o1[2] - o2[2]);
// 先把最外一圈放进去
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {
pq.offer(new int[]{i, j, heights[i][j]});
vis[i][j] = true;
}
}
}
int res = 0;
// 方向数组,把dx和dy压缩成一维来
int[] dirs = {-1, 0, 1, 0, -1};
while (!pq.isEmpty()) {
int[] poll = pq.poll();
// 看一下四个方向
for (int k = 0; k < 4; k++) {
int nx = poll[0] + dirs[k];
int ny = poll[1] + dirs[k + 1];
// 如果位置合法且没访问过
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny]) {
// 如果外围这一圈中最小的比当前这个还高,那就说明能往里面灌水啊
if (poll[2] > heights[nx][ny]) {
res += poll[2] - heights[nx][ny];
}
// 如果灌水高度得是你灌水后的高度了,如果没灌水也要取高的
pq.offer(new int[]{nx, ny, Math.max(heights[nx][ny], poll[2])});
vis[nx][ny] = true;
}
}
}
return res;
}
}