232.用栈实现队列
class MyQueue {
stack: number[];
stack2: number[];
constructor() {
this.stack = new Array();
this.stack2 = new Array();
}
push(x: number): void {
this.stack.push(x);
}
pop(): number {
while(this.stack.length){
this.stack2.push(this.stack.pop())
}
let removedVal = this.stack2.pop();
while(this.stack2.length){
this.stack.push(this.stack2.pop())
}
return removedVal;
}
peek(): number {
while(this.stack.length){
this.stack2.push(this.stack.pop())
}
let peekVal = this.stack2.pop();
this.stack2.push(peekVal);
while(this.stack2.length){
this.stack.push(this.stack2.pop())
}
return peekVal;
}
empty(): boolean {
return this.stack.length === 0;
}
}
官方题解:
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。
在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。
class MyQueue {
private stackIn: number[]
private stackOut: number[]
constructor() {
this.stackIn = [];
this.stackOut = [];
}
push(x: number): void {
this.stackIn.push(x);
}
pop(): number {
if (this.stackOut.length === 0) {
while (this.stackIn.length > 0) {
this.stackOut.push(this.stackIn.pop()!);
}
}
return this.stackOut.pop()!;
}
peek(): number {
let temp: number = this.pop();
this.stackOut.push(temp);
return temp;
}
empty(): boolean {
return this.stackIn.length === 0 && this.stackOut.length === 0;
}
}
225. 用队列实现栈
class MyStack {
private queue1: number[];
private queue2: number[];
constructor() {
this.queue1 = [];
this.queue2 = [];
}
push(x: number): void {
if (this.queue1.length > 0) {
this.queue1.push(x);
} else {
this.queue2.push(x);
}
}
pop(): number {
if (this.queue1.length > 0) {
while (this.queue1.length > 0) {
if (this.queue1.length === 1) {
let top = this.queue1.shift();
return top;
}
this.queue2.push(this.queue1.shift());
}
} else if (this.queue2.length > 0) {
while (this.queue2.length > 0) {
if (this.queue2.length === 1) {
let top = this.queue2.shift();
return top;
}
this.queue1.push(this.queue2.shift());
}
}
}
top(): number {
if (this.queue1.length > 0) {
while (this.queue1.length > 0) {
if (this.queue1.length === 1) {
let top = this.queue1.shift();
this.queue2.push(top);
return top;
}
this.queue2.push(this.queue1.shift());
}
} else if (this.queue2.length > 0) {
while (this.queue2.length > 0) {
if (this.queue2.length === 1) {
let top = this.queue2.shift();
this.queue1.push(top);
return top;
}
this.queue1.push(this.queue2.shift());
}
}
}
empty(): boolean {
return this.queue1.length === 0 && this.queue2.length === 0;
}
}
/**
* Your MyStack object will be instantiated and called as such:
* var obj = new MyStack()
* obj.push(x)
* var param_2 = obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.empty()
*/
官方题解:
版本一: 用两个队列模拟栈,由于官方题解始终只保持一个题解有值,所以
class MyStack {
private queue: number[];
private tempQueue: number[];
constructor() {
this.queue = [];
this.tempQueue = [];
}
push(x: number): void {
this.queue.push(x);
}
pop(): number {
for (let i = 0, length = this.queue.length - 1; i < length; i++) {
this.tempQueue.push(this.queue.shift()!);
}
let res: number = this.queue.pop()!;
let temp: number[] = this.queue;
this.queue = this.tempQueue;
this.tempQueue = temp;
return res;
}
top(): number {
let res: number = this.pop();
this.push(res);
return res;
}
empty(): boolean {
return this.queue.length === 0;
}
}
优化:其实这道题目就是用一个队列就够了。
一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。
class MyStack {
private queue: number[];
constructor() {
this.queue = [];
}
push(x: number): void {
this.queue.push(x);
}
pop(): number {
for (let i = 0, length = this.queue.length - 1; i < length; i++) {
this.queue.push(this.queue.shift()!);
}
return this.queue.shift()!;
}
top(): number {
let res: number = this.pop();
this.push(res);
return res;
}
empty(): boolean {
return this.queue.length === 0;
}
}
20. 有效的括号
function isValid(s: string): boolean {
let leftBrackets = [];
let brackets = [...s];
for(let bracket of brackets){
if(['(', '[', '{'].includes(bracket)){
leftBrackets.push(bracket);
} else{
let leftBracket = leftBrackets.pop();
switch(bracket){
case ')': if(leftBracket !== '(') return false; break;
case '}': if(leftBracket !== '{') return false; break;
case ']': if(leftBracket !== '[') return false; break;
}
}
}
if(leftBrackets.length > 0) return false;
return true;
};
如果 switch 后面有公共逻辑,可以不用 break; 把公共逻辑抽象出来,写到 default 里面去,类似官方题解普通版解法:
function isValid(s: string): boolean {
let helperStack: string[] = [];
for (let i = 0, length = s.length; i < length; i++) {
let x: string = s[i];
switch (x) {
case '(':
helperStack.push(')');
break;
case '[':
helperStack.push(']');
break;
case '{':
helperStack.push('}');
break;
default:
if (helperStack.pop() !== x) return false;
break;
}
}
return helperStack.length === 0;
};
官方题解优化版本:
function isValid(s: string): boolean {
type BracketMap = {
[index: string]: string;
}
let helperStack: string[] = [];
let bracketMap: BracketMap = {
'(': ')',
'[': ']',
'{': '}'
}
for (let i of s) {
if (bracketMap.hasOwnProperty(i)) {、
// 左括号
helperStack.push(bracketMap[i]);
} else if (i !== helperStack.pop()) {
// 右括号
return false;
}
}
return helperStack.length === 0;
};
hasOwnProperty()
方法返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性。
1047. 删除字符串中的所有相邻重复项
function removeDuplicates(s: string): string {
let helperStact = [];
for(let letter of s){
let lastLetterInStack = helperStact.pop();
if(!lastLetterInStack) {
helperStact.push(letter);
continue;
}
if(lastLetterInStack === letter) continue;
helperStact.push(lastLetterInStack);
helperStact.push(letter);
}
return helperStact.join('');
};