栈满足先进后出,队列满足先进先出。
# 用栈实现队列 (opens new window)
class MyQueue {
private queue: number[] = [];
push(value: number): void {
this.queue.push(value);
}
pop(): number | undefined {
return this.queue.shift();
}
peek(): number | undefined {
return this.queue[0];
}
empty(): boolean {
return !this.queue.length;
}
}
# 用队列实现栈 (opens new window)
class MyStack {
private stack: number[] = [];
push(value: number): void {
this.stack.push(value);
}
pop(): number | undefined {
return this.stack.shift();
}
top(): number {
const n = this.stack.length;
return this.stack[n - 1];
}
empty(): boolean {
return !this.stack.length;
}
}
# 滑动窗口的最小值 (opens new window)
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里面的最大值。
function maxSlidingWindow(nums: number[], k: number): number[] {
const { length } = nums;
if (!k || !length) return [];
const deque: number[] = [];
for (let i = 0; i < k; i++) {
cleanDeque(deque, nums, i, k);
deque.push(i);
}
const res: number[] = [];
res.push(nums[deque[0]]);
for (let i = k; i < length; ++i) {
cleanDeque(deque, nums, i, k);
deque.push(i);
res.push(nums[deque[0]]);
}
return res;
}
/**
* 刷新双端队列
* @param queue
* @param nums
* @param index
* @param k
*/
function cleanDeque(
queue: number[],
nums: number[],
index: number,
k: number
): void {
// 如果双向队列中包含不是滑动窗口的数,直接出队
if (queue.length && index >= k + queue[0]) {
queue.shift();
}
while (queue.length && nums[index] > nums[queue[queue.length - 1]]) {
queue.pop();
}
}
# 有效的括号 (opens new window)
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。
function isValid(s: string): boolean {
const n = s.length
if (n % 2) return false
const stack: string[] = []
let index = 0
while (index < n) {
const letter = s[index]
if (letter === '(' || letter === '{' || letter === '[') stack.push(letter)
else {
switch (letter) {
case ')': {
if (stack.pop() !== '(') return false
break
}
case '}': {
if (stack.pop() !== '{') return false
break
}
case ']': {
if (stack.pop() !== '[') return false
break
}
}
}
index++
}
return !stack.length
}
# 字符串解码 (opens new window)
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
function decodeString(s: string): string {
const stack: string[] = []
for (const char of s) {
if (char !== ']') {
stack.push(char)
continue
}
// 每当遇到 ']' 的时候,就可以把栈里面的数据取出来,然后计算出之前的字母的数量
let cur = stack.pop()
let str = '' // 括号内的字母
while (cur !== '[') {
str = cur + str
cur = stack.pop()
}
cur = stack.pop()
let num = '' // 括号前的数字
while (!isNaN(+cur!)) {
num = cur + num
cur = stack.pop()
}
cur && stack.push(cur) // 把上一次的字母加回去
stack.push(str.repeat(+num))
}
return stack.join('')
}
# 根据身高建队列 (opens new window)
假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。
注意: 总人数少于1100人。
function reconstructQueue(people: number[][]): number[][] {
const n = people.length
if (!n) return []
// 按身高进行降序排列,然后按照前面的人数进行升序排列
people.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : b[0] - a[0]))
const res: number[][] = []
for (let i = 0; i < n; i++) {
res.splice(people[i][1], 0, people[i])
}
return res
}
# 数组中的第 k 个最大元素 (opens new window)
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
function findKthLargest(nums: number[], k: number): number {
nums.sort((a, b) => b - a)
return nums[k - 1]
}