Q17- code225-用队列实现栈
实现思路
方法1.1: 双队列- 易push难pop
1 双队列:关键是对最后一个元素进行特殊处理:排除 && 返回其值
方法1.2: 双队列 + topV- 易push和top,难pop
1 在 双队列基础上,额外通过一个变量,来记录栈顶元素,从而减少top耗时
方法2: 单队列 + 弹出后弹入- 难push,易pop
1 关键在于 添加x--> 弹出--> 在加入的 操作逻辑步骤
参考文档
代码实现
1 方法1.1: 双队列- 易push难pop 时间复杂度: O(n) 空间复杂度: O(1)
// 方法1.1
class MyStack {
queue: Array<number>;
constructor() {
this.queue = [];
}
push(x: number): void {
this.queue.push(x);
}
pop(): number {
// 第2个临时q2:
// 除最后一个元素,都按序移到p2--> 移除最后一个元素--> 把p2移回p1
if (this.empty()) return;
let q2 = [];
// 除最后一个元素,都按序移到p2
while (this.queue.length > 1) {
q2.push(this.queue.shift());
}
// 移除最后一个元素
let lastV = this.queue.shift();
// 把p2移回p1
while (q2.length) {
this.queue.push(q2.shift());
}
return lastV;
}
top(): number {
// 直接复用pop即可
const lastV = this.pop();
this.push(lastV);
return lastV;
}
empty(): boolean {
return this.queue.length === 0;
}
}
2 方法1.2: 双队列 + topV- 易push和top,难pop 时间复杂度: O(n) 空间复杂度: O(1)
class MyStack {
queue: Array<number>;
topV: null | number
constructor() {
this.queue = [];
this.topV = null
}
push(x: number): void {
this.queue.push(x);
this.topV = x
}
pop(): number {
// 第2个临时q2:
// 除最后一个元素,都按序移到p2--> 移除最后一个元素--> 把p2移回p1
if (this.empty()) return;
let q2 = [];
// 除最后一个元素,都按序移到p2
while (this.queue.length > 1) {
q2.push(this.queue.shift());
}
// 移除最后一个元素
let lastV = this.queue.shift();
// 把p2移回p1, 通过this.push来 自动跟新lastV的值
while (q2.length) {
this.push(q2.shift());
}
return lastV;
}
top(): number {
// 直接返回 topV即可
return this.topV;
}
empty(): boolean {
return this.queue.length === 0;
}
}
3 方法2: 单队列 + 弹出后弹入- 难push,易pop 时间复杂度: O(n) 空间复杂度: O(1)
class MyStack {
queue: Array<number>;
constructor() {
this.queue = [];
}
push(x: number): void {
// 记录添加x前的 队列已有内容数量--> 加入x--> 弹出x之前的内容 & 重新推入x之前的内容
let size = this.queue.length;
this.queue.push(x);
while (size > 0) {
this.queue.push(this.queue.shift());
size--;
}
}
pop(): number {
return this.queue.shift();
}
top(): number {
return this.queue[0];
}
empty(): boolean {
return this.queue.length === 0;
}
}
Q18- code346-从数据流中移动平均值
实现思路
方法1.1:
1 节省时间的技巧:通过队列 + sum变量,来记录已有的sum值,从而简化求和操作
参考文档
代码实现
1 方法1.1: 队列 时间复杂度: O(1) 空间复杂度: O(n)
class MovingAverage {
private size: number;
private queue: number[] = [];
private sum: number;
constructor(size: number) {
this.size = size;
this.queue = [];
this.sum = 0;
}
next(val: number): number {
if (this.queue.length === this.size) {
let x = this.queue.shift();
this.sum -= x;
}
this.queue.push(val);
this.sum += val;
// 返回结果
return this.sum / this.queue.length;
}
}
Q19- code281-之字形迭代器
实现思路
方法1.1:
1 队列记录的结构是一个自定义对象: Array< { arr: number[]; idx: number } >
2 通过这个自定义对象里的idx,配合队列的push+shift,就能实现 k个队列的读取操作
参考文档
代码实现
1 方法1.1: 队列 & 当前索引定位 时间复杂度: O(n) 空间复杂度: O(1)
class ZigzagIterator {
private queue: Array<{
arr: number[];
idx: number;
}>;
constructor(v1: number[], v2: number[]) {
this.queue = [];
if (v1.length > 0) this.queue.push({ arr: v1, idx: 0 });
if (v2.length > 0) this.queue.push({ arr: v2, idx: 0 });
}
// 支持是k个数组的情况:修改构造函数,接收数组的数组
// constructor(vectors: number[][]) {
// this.queue = [];
// // 将所有非空数组加入队列
// for (const arr of vectors) {
// if (arr.length > 0) {
// this.queue.push({ arr, index: 0 });
// }
// }
// }
next(): number {
if (!this.hasNext()) return -1;
const { arr, idx } = this.queue.shift();
const val = arr[idx];
if (idx + 1 < arr.length) {
this.queue.push({ arr, idx: idx + 1 });
}
return val;
}
hasNext(): boolean {
return this.queue.length > 0;
}
}
Q20 code1429-第一个唯一数字
实现思路
方法1: HashMap + Queue
1 通过 Map记录 当前数字是否唯一
2.1 通过 queue 来存储所有唯一值
2.2 通过 qIdx 来记录第一个唯一值的位置,从而避免频繁出栈+查询
参考文档
代码实现
1 方法1: HashMap + Queue
时间复杂度:
- init: O(n)
- add: O(n), 均摊时间复杂度: O(1)
- showFirstUnique: O(1)
空间复杂度: O(n)
class FirstUnique {
private uniqueMap: Map<number, Boolean> = new Map()
private q: number[] = []
private qIdx: number = 0
constructor(nums: number[]) {
for (let val of nums) {
this.add(val)
}
}
add(value: number): void {
// 记录当前数字value 是否唯一
if (!this.uniqueMap.has(value)) {
this.uniqueMap.set(value, true)
} else {
this.uniqueMap.set(value, false)
}
// 如果当前数字value 是唯一的,则加入队列
if (this.uniqueMap.get(value)) {
this.q.push(value)
}
// 把 qIdx 指向 队列中的第一个 唯一数字
while (this.qIdx < this.q.length &&
!this.uniqueMap.get(this.q[this.qIdx])) {
this.qIdx++
}
}
showFirstUnique(): number {
if (this.qIdx < this.q.length) {
return this.q[this.qIdx]
}
return -1
}
}