Leetcode 232.用栈实现队列
题目:232.用栈实现队列
初始思路
之前写过用数组实现队列,但是调用了数组的一些API,这里题目要求必须要用两个栈。
代码
var MyQueue = function () {// 输入和输出栈this.stackIn = []this.stackOut = []};/*** @param {number} x* @return {void}* 将元素 x 推到队列的末尾*/MyQueue.prototype.push = function (x) {this.stackIn.push(x)};/*** @return {number}* 从队列的开头移除并返回元素*/MyQueue.prototype.pop = function () {const size = this.stackOut.length// 如果输出栈不为空的话,直接弹出即可if (size) {return this.stackOut.pop()}// 如果输出栈为空的话,要把输出栈的所有元素搬到输出栈中开始弹出while (this.stackIn.length) {this.stackOut.push(this.stackIn.pop())}return this.stackOut.pop()};/*** @return {number}* 返回队列开头的元素*/MyQueue.prototype.peek = function () {// pop函数返回队列开头的元素const x = this.pop()// 改变了队列,再改回去this.stackOut.push(x)return x};/*** @return {boolean}* 如果队列为空,返回 true ;否则,返回 false*/MyQueue.prototype.empty = function () {return !this.stackIn.length && !this.stackOut.length};/*** Your MyQueue object will be instantiated and called as such:* var obj = new MyQueue()* obj.push(x)* var param_2 = obj.pop()* var param_3 = obj.peek()* var param_4 = obj.empty()*/
感想
- 使用输入和输出栈。
- 在push数据的时候,只要数据放进输入栈就好
- 在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
- peek很巧妙,通过pop直接获取队列开头的元素,然后再放回去。
- 如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。
Leetcode 225.用队列实现栈
题目:225.用队列实现栈
初始思路
还是用数组,如果是队列的话,那数组只能用push和shift方法,因为只能在队列开头操作
代码
var MyStack = function () {this.queue = []};/*** @param {number} x* @return {void}* 将元素 x 压入栈顶。*/MyStack.prototype.push = function (x) {this.queue.push(x)};/*** @return {number}* 移除并返回栈顶元素。*/MyStack.prototype.pop = function () {let size = this.queue.lengthwhile (size-- > 1) {this.queue.push(this.queue.shift())}return this.queue.shift()};/*** @return {number}* 返回栈顶元素。*/MyStack.prototype.top = function () {const x = this.pop()this.queue.push(x)return x};/*** @return {boolean}* 如果栈是空的,返回 true ;否则,返回 false 。*/MyStack.prototype.empty = function () {return !this.queue.length};/*** 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()*/
var MyStack = function () {this.queue1 = [];this.queue2 = [];};/*** Push element x onto stack.* @param {number} x* @return {void}*/MyStack.prototype.push = function (x) {this.queue1.push(x);};/*** Removes the element on top of the stack and returns that element.* @return {number}*/MyStack.prototype.pop = function () {// 减少两个队列交换的次数, 只有当queue1为空时,交换两个队列// 也就是当queue1中的元素都弹出完毕的时候if (!this.queue1.length) {[this.queue1, this.queue2] = [this.queue2, this.queue1];}// 把queue1中除了最后一个元素都放入queue2while (this.queue1.length > 1) {this.queue2.push(this.queue1.shift());}// 弹出最后面的元素return this.queue1.shift();};/*** Get the top element.* @return {number}*/MyStack.prototype.top = function () {const x = this.pop();this.queue1.push(x);return x;};/*** Returns whether the stack is empty.* @return {boolean}*/MyStack.prototype.empty = function () {return !this.queue1.length && !this.queue2.length;};
感想
- 单队列实现很精妙。在pop方法中,把除了栈顶的元素先弹出在压入,不会改变顺序。
- 两个队列实现中,pop方法:把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。
Leetcode 20.有效的括号
题目:20.有效的括号
初始思路
以前在数据结构课上听过,应该是栈的经典应用。在压栈过程中,如果左括号遇到了匹配的右括号就弹栈。
代码
var isValid = function (s) {let stack = []for (let i = 0; i < s.length; i++) {let ch = s[i]// 如果是左括号就入栈if (ch === '(' || ch === '[' || ch === '{') {stack.push(ch)} else if (ch === ')' || ch === ']' || ch === '}') {// 如果是右括号就和栈顶元素进行匹配// 栈顶元素const p = stack[stack.length - 1]if ((ch === ')' && p === '(') || (ch === ']' && p === '[') || (ch === '}' && p === '{')) {// 如果匹配成功就弹出栈顶这个左括号,继续匹配stack.pop()} else {return false}}}// 当栈内元素都弹出的时候,匹配完成return stack.length === 0};
var isValid = function (s) {const stack = [];for (let i = 0; i < s.length; i++) {let c = s[i];switch (c) {case '(':stack.push(')');break;case '[':stack.push(']');break;case '{':stack.push('}');break;default:if (c !== stack.pop()) {return false;}}}return stack.length === 0;};// 简化版本var isValid = function(s) {const stack = [],map = {"(":")","{":"}","[":"]"};for(const x of s) {if(x in map) {stack.push(x);continue;};if(map[stack.pop()] !== x) return false;}return !stack.length;};
感想
- 实现起来其实不困难,挺好写的。但是简单写起来有些繁琐,比起简化版版本来说有些笨拙。
Leetcode 1047.删除字符串中的所有相邻重复项
初始思路
自己尝试用栈模拟了一下,感觉挺对的。再看一下题解,原来自己模拟的不对,好吧!
代码
var removeDuplicates = function (s) {let stack = []for (const ch of s) {// 栈顶元素let p = stack[stack.length - 1]if (stack.length && p === ch) {// 如果栈不为空并且匹配上了就弹出stack.pop()} else {stack.push(ch)}}return stack.join('')};
var removeDuplicates = function (s) {// 解构赋值成数组s = [...s]// 指向栈顶元素的下标let top = -1for (let i = 0; i < s.length; i++) {// 栈为空哦或者不匹配if (top === -1 || s[top] !== s[i]) {// 入栈s[++top] = s[i]} else {// 出栈top--}}// 栈顶元素下标 + 1 为栈的长度s.length = top + 1return s.join('')}
感想
- 思路挺简单的。
- 为什么还能用双指针?
