算法打卡第一天

101 阅读3分钟

算法打卡第一天

  1. 剑指 Offer 09. 用两个栈实现队列
  2. 剑指 Offer 30. 包含min函数的栈

剑指 Offer 09. 用两个栈实现队列

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

理解题意:

  1. CQueue 为要实现的队列,描述中用两个栈实现一个队列,所以需要初始化两个栈,一个负责存储加入的数据stack1,一个负责删除的数据stack2
  2. appendTail 函数为队列插入数据,stack1为负责存储加入的数据,所以只需要push() 就行
  3. deleteHead 负责删除队列头部数据, 因为队列是先进先出的,而栈是先进后出原则。删除时需要考虑一下几种情况 (1) stack1和stack2都为空,即还没加入数据就执行删除,返回-1 (2) stack1不为空,先将 stack2为空。先将stack1的所有数据push进stack2中 (3) stack1不为空,先将 stack2不为空。直接返回stack2出栈结果 (4) stack1为空,先将 stack2不为空。直接返回stack2出栈结果 特别需要注意的是第二步,我就犯了一个错,没有将stack1中所有的数据入栈stack1中,导致出栈顺序不对 解法1 如上 (超过时间:82.7%,内存:52.3%) 解法2 解法前两步都相同,最后一步顺序不同 (超过时间:55%,内存:66%) (1) stack1不为空,先将 stack2为空。先将stack1的所有数据push进stack2中 (2) stack2为空,stack1不为空,即还没加入数据就执行删除,返回-1 (3) stack2为空,stack1为空,即还没加入数据就执行删除,返回-1 (4) stack1为空,先将stack2不为空。直接返回stack2出栈结果

总结: stack1 永远负责入栈 stack2 永远负责出栈 stack2 stack2没有数据,要把stack1中的所有数据都放入2;有数据先出,stack2就只出栈就行

var CQueue = function() {
    this.stack1=[]
    this.stack2=[]
};

/** 
 * @param {number} value
 * @return {void}
 */
CQueue.prototype.appendTail = function(value) {
    this.stack1.push(value)
};

/**
 * @return {number}
 */
CQueue.prototype.deleteHead = function() {
    // 解法1
    if(!this.stack1.length && !this.stack2.length){
        return -1;
    }
    if(!this.stack2.length){
        while (this.stack1.length) {
            this.stack2.push(this.stack1.pop())
        }
    }
    return this.stack2.pop();

    // 解法2
    // if(!this.stack2.length && this.stack1.length){
    //     while (this.stack1.length) {
    //         this.stack2.push(this.stack1.pop())
    //     }
    // }
    // if(!this.stack2.length){
    //     return -1;
    // }else{
    //     return this.stack2.pop();
    // }
};
// 用例1:
// 输入:
// ["CQueue","appendTail","deleteHead","deleteHead"]
// [[],[3],[],[]]
// 输出:[null,null,3,-1]


// 用例2
// 模拟实现
const a = new CQueue()
// 输入1
const arr=["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"] 
// 输入2
const arr1=[[],[],[5],[2],[],[]]
// 运行结构
const output=[];

for (let i = 0; i < arr.length; i++) {
    if(arr[i]==="CQueue"){
        output.push(null)
    }else if(arr[i]==="appendTail"){
        a.appendTail(arr1[i])
        output.push(null)
    }else if(arr[i]==="deleteHead"){
        const num=a.deleteHead();
        output.push(Array.isArray(num)?num[0]:num)
    }
}
console.log(output); // [null,-1,null,null,5,2]

剑指 Offer 30. 包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

理解题意: MinStack的min方法来查找最小数 时间复杂度为1

  1. 定义两个栈,一个用来存储正常数据stack,一个用来存储当最小数的栈minStack
  2. push方法 stack正常入栈操作;在push的时候就进行比对,当前数与minStack中顶部数比较,存储较小值
  3. pop方法 stack和minStack正常出栈
  4. top方法 返回stack栈顶元素
  5. min方法 返回minStack栈顶元素

此方法超过执行时间超过99%

/**
 * initialize your data structure here.
 */
var MinStack = function() {
    this.stack = []
    this.minStack = []
};

/** 
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
    this.stack.push(x)
    if(this.minStack.length){
        this.minStack.push(Math.min(this.minStack[this.minStack.length-1],x))
        return
    }
    this.minStack.push(x)
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    this.stack.pop()
    this.minStack.pop()
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    return this.stack[this.stack.length - 1]
};

/**
 * @return {number}
 */
MinStack.prototype.min = function() {
    if(!this.minStack.length){
        return -1
    }
    return this.minStack[this.minStack.length-1]
};