LeetCode 150.逆波兰表达式求值
📖 考察点
栈的应用
📖 题意理解
💡 解题思路
数字入栈,字符出栈两个,结果入栈
🔑 关键点总结
💻 代码实现
JavaScript
var evalRPN = function (tokens) {
let stack = [];
for (let char of tokens) {
switch (char) {
case "+": {
let right = +stack.pop();
let left = +stack.pop();
stack.push(left + right);
break;
}
case "-": {
let right = +stack.pop();
let left = +stack.pop();
stack.push(left - right);
break;
}
case "/": {
let right = +stack.pop();
let left = +stack.pop();
stack.push(~~(left / right));
break;
}
case "*": {
let right = +stack.pop();
let left = +stack.pop();
stack.push(left * right);
break;
}
default: {
stack.push(char);
break;
}
}
}
return +stack.pop();
};
Rust
⏱️ 复杂度分析
📚 总结与反思
LeetCode 239. 滑动窗口最大值
📖 考察点
自定义单调队列
📖 题意理解
给你一个整数数组 nums,有一个大小为 k **的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值
💡 解题思路
思路一:
思路二:
🔑 关键点总结
💻 代码实现
JavaScript
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var maxSlidingWindow = function (nums, k) {
const deQueue = [];
const pop = (num) => {
if (deQueue.length && deQueue[0] === num) {
deQueue.shift();
}
};
const push = (num) => {
while (num >= deQueue[deQueue.length - 1]) {
deQueue.pop();
}
deQueue.push(num);
};
const getMaxValue = (num) => {
return deQueue[0];
};
let res = [];
for (let i = 0; i < nums.length; i++) {
push(nums[i]);
if (i >= k - 1) {
pop(nums[i - k]);
res.push(getMaxValue());
}
}
return res;
};
Rust
⏱️ 复杂度分析
📚 总结与反思
LeetCode 347.前 K 个高频元素
📖 考察点
哈希表 堆的应用 堆的实现
📖 题意理解
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
💡 解题思路
维护一个k个元素的小顶堆,超过k个元素弹出栈顶元素。
思路一:
思路二:
🔑 关键点总结
💻 代码实现
JavaScript
class MyHeap {
constructor(compareFn) {
this.heap = [];
this.compareFn = compareFn;
}
get size() {
return this.heap.length;
}
compare(left, right) {
return this.compareFn(this.heap[left], this.heap[right]);
}
swap(i, j) {
let temp = this.heap[i];
this.heap[i] = this.heap[j];
this.heap[j] = temp;
}
getParentIndex = (index) => {
return ~~((index - 1) / 2);
};
getLeftChildIndex = (index) => {
return index * 2 + 1;
};
insert(value) {
this.heap.push(value);
this.heapifyUp(this.heap.length - 1);
}
extractTop() {
if (this.heap.length === 0) {
return null;
}
const max = this.heap[0];
const last = this.heap.pop();
if (this.size > 0) {
this.heap[0] = last;
this.heapifyDown();
}
return max;
}
heapifyUp(index) {
let parentIndex = this.getParentIndex(index);
while (index > 0 && this.compare(parentIndex, index) > 0) {
this.swap(index, parentIndex);
index = parentIndex;
parentIndex = this.getParentIndex(index);
}
}
heapifyDown() {
let current = 0;
do {
let next = current;
let leftChildIndex = this.getLeftChildIndex(current);
let rightChildIndex = leftChildIndex + 1;
if (leftChildIndex < this.size && this.compare(next, leftChildIndex) > 0) {
next = leftChildIndex;
}
if (rightChildIndex < this.size && this.compare(next, rightChildIndex) > 0) {
next = rightChildIndex;
}
if (next !== current) {
this.swap(next, current);
current = next;
} else {
break;
}
} while (true);
}
}
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function (nums, k) {
const map = new Map();
const heap = new MyHeap((a, b) => a[1] - b[1]);
for (let num of nums) {
let count = map.get(num);
if (count) {
map.set(num, count + 1);
} else {
map.set(num, 1);
}
}
for (let record of map.entries()) {
heap.insert(record);
if (heap.size > k) {
heap.extractTop();
}
}
return heap.heap.map((record) => record[0]);
};
Rust
⏱️ 复杂度分析
📚 总结与反思
执行交换的条件应保持一致,注意处理index的范围。超过范围的不可以执行。向下堆化时,左右都应该执行一次compare