【前端js】实现剑指offer|leetcode(三)——栈和队列题目集合

文章目录

    • 一、栈
        • 1. 用两个栈实现队列(牛客网-剑指offer)
        • 2. 包含min函数的栈(牛客网-剑指offer)
        • 3. 栈的压入、弹出序列(牛客网-剑指offer)


一、栈

1. 用两个栈实现队列(牛客网-剑指offer)

题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

测试用例

  1. 空队列入队出队
  2. 非空队列入队出队
  3. 连续出队直到队列为空

思路

  • 栈只能从栈顶出入,队列从队首出,队尾入,借助两个栈:栈1的顶为队尾栈2的顶为队首
  • push 从队尾压入一个元素,从s1压入,栈空和非空情况一样,无返回值
  • pop 从队首一个弹出元素,s2不空时队首在s2栈顶s2空时队首在s1栈底,需要先把s1中所有元素依次弹入s2,然后弹出s2栈顶
  • 注意从A中弹出所有元素压入B时,因为A数组改变,所以需要先把数组长度存下来,再使用保存的值控制for循环
  • 如果s1空,队列为空,pop弹出null

【前端js】实现剑指offer|leetcode(三)——栈和队列题目集合_第1张图片

  • 代码
var stack1 = [],
  // var stack1 = [],
  stack2 = []; //定义两个栈
//入队,修改原数组,无返回值
function push(node) {
  // write code here
  stack1.push(node); //压入栈1
}
//出队,修改原数组,返回出队元素
function pop() {
  // write code here
  //栈2不空,返回栈2栈顶元素
  if (stack2.length !== 0) return stack2.pop();
  //栈2空,返回栈1栈底元素
  if (stack2.length === 0) {
    //栈1空,返回空
    if (stack1.length === 0) return null;
    //栈1不空,将栈1元素全部放入栈2,然后返回栈顶元素
    let len =stack1.length;//for循环修改了stack1数组,所以要先保存len作为循环的计数器
    for (let i = 0; i < len; i++) {
      stack2.push(stack1.pop());
    }
    return stack2.pop();
  }
}


2. 包含min函数的栈(牛客网-剑指offer)

题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数,时间复杂度应为O(1)

测试用例

  1. push——入栈元素是第一个,入栈元素是当前最小值,入栈元素不是当前最小值,
  2. pop——出栈元素不是当前最小值,入栈元素是当前最小值
  3. pop——连续出栈直到栈为空
  4. min——栈为空,栈不为空

思路

  • 时间复杂度应为O(1)所以应该保存每次栈压入元素之后的最小值,新建一个stkMin,和stk同步
  • push——栈元素是第一个,入栈元素是当前最小值时,stkMin压入node,否则压入stkMin栈顶元素(之前的最小值依然是最小值)
  • pop——stkMinstk同步出栈
  • min——返回stkMin栈顶元素

代码

var stk = [];
var stkMin = [];
function push(node) {
  // write code here
  stk.push(node);
  stkMin.length === 0 || node < stkMin[stkMin.length - 1]
    ? stkMin.push(node) //stkMin空/node小于栈顶元素时,node为最小值
    : stkMin.push(stkMin[stkMin.length - 1]); //node大于栈顶元素时,栈顶元素为最小值
}
function pop() {
  // write code here
  if (stk.length === 0) return null;
  stkMin.pop();
  return stk.pop();
}
 function top() {
   // write code here
   return stk[stk.length - 1]; //返回栈顶元素
 }
function min() {
  // write code here
  return stkMin[stkMin.length - 1];
}

3. 栈的压入、弹出序列(牛客网-剑指offer)

题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。

测试用例

  1. 特殊情况1——两个数组中一个/两个为空,或者长度不相等
  2. 特殊情况2——两个数组只有一个元素
  3. 正确——是弹出序列
  4. 错误——不是弹出序列

思路

  • 判断一个序列是不是栈的弹出序列,其实是判断将序列1压入栈时,栈顶元素是否可以形成序列2,栈顶元素有三种可能:
  • 1.当前栈顶
  • 2.弹出栈顶之后的新栈顶
  • 3.继续压入新的栈顶
  • 比较顺序:1,2,3,可以最多的弹出所有元素
  • 借助一个辅助栈,依次把所有元素压入这个栈里,设置一个指针idx指向需要弹出的元素,初始指向弹出序列的第一个元素
  • 每次压入之后,都比较idx元素和栈顶元素是否相等,如果相等,就弹出这个值,idx指向下一个,循环比较所有相等值全部弹出,直到两个值不等,不再弹出序列,继续压入
  • 数组里所有元素都压栈完成以后,如果辅助栈还有没弹出的元素,就代表
    不是弹出序列,如果栈空了,就代表是弹出序列

代码

function IsPopOrder(pushV, popV) {
  // write code here
  //任意空数组/数组长度不相等,不满足条件
  if (pushV.length === 0 || popV.length === 0 || popV.length !== pushV.length)
    return false;
  //单个数组,比较一个元素
  if (pushV.length === 1 && popV.length === 1) return pushV[0] === popV[0];
  let stk = []; //辅助栈
  let idx = 0; //指针,指向popV的第一个元素
  //将pushV压入辅助栈
  for (let i = 0; i < pushV.length; i++) {
    stk.push(pushV[i]);
    // stk空或者栈顶元素和popV指针的元素不相等,跳过循环,继续入栈
    // 栈顶元素和popV指针的元素相等时,循环比较栈顶元素和pop中指针指向的元素
    while (stk.length != 0 && stk[stk.length - 1] === popV[idx]) {
      stk.pop(); // 栈顶元素出栈
      idx++; //指针下移,继续比较
    }
  }
  return stk.length === 0; //所有popV中的元素都按顺序出栈,则是一个弹出序列
}
IsPopOrder([1, 2, 3, 4, 5], [4, 5, 3, 2, 1]);
IsPopOrder([1], [2]);

你可能感兴趣的:(【前端js】实现剑指offer|leetcode(三)——栈和队列题目集合)