Stay Hungry, Stay Foolish

设计一个有getMin功能的栈

在实现栈的基本功能的基础上,再实现返回栈中所有元素的最小值:
其中一种思想是用两个栈,一个栈作为常规的栈dataStack,另一个栈来维护当前栈内最小值minStack。入栈的时候如果常规栈为空,则将入栈值同时放入minStack和dataStack,否则比较入栈值和minStack栈顶元素的大小关系,如果小于或等于minStack栈顶元素值,则同时将入栈值压入minStack,否则不操作minStack。在出栈前比较minStack和dataStack栈顶元素的大小如果dataStack的栈顶元素小于等于minStack的栈顶元素,则同时弹出栈顶元素,否则仅弹出dataStack的栈顶元素,完成出栈操作。
以下操作入栈均使用数组[2, 3, 5, 1, 3, 1, 2]
python实现如下:

class myStack:
    dataStack=[]
    minStack=[]
    def getMin(self):
        if self.dataStack:
            return self.minStack[-1]
        return None

    def push(self,ivalue):
        if self.minStack:
            if self.minStack[-1]>=ivalue:
                self.minStack.append(ivalue)
        else:
            self.minStack.append(ivalue)
        self.dataStack.append(ivalue)
        print('入栈值',ivalue)
        print('dataStack:', self.dataStack)
        print(' minStack:', self.minStack)

    def pop(self):
        p=None
        if self.dataStack:
            p=self.dataStack.pop()
            if p<=self.minStack[-1]:
                self.minStack.pop()
        print('出栈值', p)
        print('dataStack:', self.dataStack)
        print(' minStack:', self.minStack)
        return p

运行结果如下:

入栈值 2 ,getMin: 2
dataStack: [2]
 minStack: [2]
入栈值 3 ,getMin: 2
dataStack: [2, 3]
 minStack: [2]
入栈值 5 ,getMin: 2
dataStack: [2, 3, 5]
 minStack: [2]
入栈值 1 ,getMin: 1
dataStack: [2, 3, 5, 1]
 minStack: [2, 1]
入栈值 3 ,getMin: 1
dataStack: [2, 3, 5, 1, 3]
 minStack: [2, 1]
入栈值 1 ,getMin: 1
dataStack: [2, 3, 5, 1, 3, 1]
 minStack: [2, 1, 1]
入栈值 2 ,getMin: 1
dataStack: [2, 3, 5, 1, 3, 1, 2]
 minStack: [2, 1, 1]
出栈值 2 ,getMin: 1
dataStack: [2, 3, 5, 1, 3, 1]
 minStack: [2, 1, 1]
出栈值 1 ,getMin: 1
dataStack: [2, 3, 5, 1, 3]
 minStack: [2, 1]
出栈值 3 ,getMin: 1
dataStack: [2, 3, 5, 1]
 minStack: [2, 1]
出栈值 1 ,getMin: 2
dataStack: [2, 3, 5]
 minStack: [2]
出栈值 5 ,getMin: 2
dataStack: [2, 3]
 minStack: [2]
出栈值 3 ,getMin: 2
dataStack: [2]
 minStack: [2]
出栈值 2 ,getMin: None
dataStack: []
 minStack: []

上面的实现方式在入栈和出栈都要进行判断,判断是需要时间成本的。入栈的判断是不能省去的,如果每次入栈的时候都压入值到minStack,那出栈的时候就不用做任何判断直接弹出minStack的栈顶值,这样minStack中元素始终和dataStack中元素数目相等。想完成这个想法只需每次向dataStack中压入数据的时候同时向minStack压入min(minStack[-1],待压入元素)即可。
实现如下:

class myStack1:
    dataStack=[]
    minStack=[]
    def getMin(self):
        if self.dataStack:
            return self.minStack[-1]
        return None

    def push(self,ivalue):
        if self.minStack:
            if self.minStack[-1]>=ivalue:
                self.minStack.append(ivalue)
            else:
                self.minStack.append(self.minStack[-1])
        else:
            self.minStack.append(ivalue)
        self.dataStack.append(ivalue)
        print('入栈值', ivalue, ',getMin:', self.getMin())
        print('dataStack:', self.dataStack)
        print(' minStack:', self.minStack)

    def pop(self):
        p=None
        if self.dataStack:
            self.minStack.pop()
            p= self.dataStack.pop()

        print('出栈值', p, ',getMin:', self.getMin())
        print('dataStack:', self.dataStack)
        print(' minStack:', self.minStack)
        return p

运行结果如下,可以看到任何时刻minStack和dataStack中的元素数目都是相等的:

入栈值 2 ,getMin: 2
dataStack: [2]
 minStack: [2]
入栈值 3 ,getMin: 2
dataStack: [2, 3]
 minStack: [2, 2]
入栈值 5 ,getMin: 2
dataStack: [2, 3, 5]
 minStack: [2, 2, 2]
入栈值 1 ,getMin: 1
dataStack: [2, 3, 5, 1]
 minStack: [2, 2, 2, 1]
入栈值 3 ,getMin: 1
dataStack: [2, 3, 5, 1, 3]
 minStack: [2, 2, 2, 1, 1]
入栈值 1 ,getMin: 1
dataStack: [2, 3, 5, 1, 3, 1]
 minStack: [2, 2, 2, 1, 1, 1]
入栈值 2 ,getMin: 1
dataStack: [2, 3, 5, 1, 3, 1, 2]
 minStack: [2, 2, 2, 1, 1, 1, 1]
出栈值 2 ,getMin: 1
dataStack: [2, 3, 5, 1, 3, 1]
 minStack: [2, 2, 2, 1, 1, 1]
出栈值 1 ,getMin: 1
dataStack: [2, 3, 5, 1, 3]
 minStack: [2, 2, 2, 1, 1]
出栈值 3 ,getMin: 1
dataStack: [2, 3, 5, 1]
 minStack: [2, 2, 2, 1]
出栈值 1 ,getMin: 2
dataStack: [2, 3, 5]
 minStack: [2, 2, 2]
出栈值 5 ,getMin: 2
dataStack: [2, 3]
 minStack: [2, 2]
出栈值 3 ,getMin: 2
dataStack: [2]
 minStack: [2]
出栈值 2 ,getMin: None
dataStack: []
 minStack: []

既然元素相同行得通,有没有可能只用一个栈来实现题目的要求呢,当然是可以的,我往栈中压入元组如何呢[1,1],左边元素相当于dataStack中元素,右边元素相当于minStack中的元素。
python实现如下:

class myStack2:
    dataStack=[]
    def getMin(self):
        if self.dataStack:
            return self.dataStack[-1][1]
        return None

    def push(self,ivalue):
        if self.dataStack:
            tpmin=self.dataStack[-1][1]
            if tpmin>ivalue:
                self.dataStack.append((ivalue,ivalue))
            else:
                self.dataStack.append((ivalue,tpmin))
        else:
            self.dataStack.append((ivalue, ivalue))
        print('入栈值', ivalue, ',getMin:', self.getMin())
        print('dataStack:', self.dataStack)
        
    def pop(self):
        p=None
        if self.dataStack:
            p=self.dataStack.pop()
            p=p[0]
        print('出栈值', p, ',getMin:', self.getMin())
        print('dataStack:', self.dataStack)

        return p

我们来运行一下:

入栈值 2 ,getMin: 2
dataStack: [(2, 2)]
入栈值 3 ,getMin: 2
dataStack: [(2, 2), (3, 2)]
入栈值 5 ,getMin: 2
dataStack: [(2, 2), (3, 2), (5, 2)]
入栈值 1 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1)]
入栈值 3 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1), (3, 1)]
入栈值 1 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1), (3, 1), (1, 1)]
入栈值 2 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1), (3, 1), (1, 1), (2, 1)]
出栈值 2 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1), (3, 1), (1, 1)]
出栈值 1 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1), (3, 1)]
出栈值 3 ,getMin: 1
dataStack: [(2, 2), (3, 2), (5, 2), (1, 1)]
出栈值 1 ,getMin: 2
dataStack: [(2, 2), (3, 2), (5, 2)]
出栈值 5 ,getMin: 2
dataStack: [(2, 2), (3, 2)]
出栈值 3 ,getMin: 2
dataStack: [(2, 2)]
出栈值 2 ,getMin: None
dataStack: []

嗯,功能是一样的,但是有什么区别呢。我们来上一千万次入栈和出栈操作试试!!!!

def test():
    st = myStack()
    tst = time.time()
    for i in range(10000000):
        st.push(1)
    for j in range(10000000):
        st.pop()

    ted = time.time() - tst
    print('myStack time:', ted)

    del st
    time.sleep(2)

    st=myStack1()
    tst=time.time()
    for i in range(10000000):
        st.push(1)
    for j in range(10000000):
        st.pop()

    ted=time.time()-tst
    print('myStack1 time:',ted)

    del st
    time.sleep(2)

    st = myStack2()
    tst = time.time()
    for i in range(10000000):
        st.push(1)
    for j in range(10000000):
        st.pop()
    ted = time.time() - tst
    print('myStack2 time:', ted)

结果:

myStack time: 7.706661224365234
myStack1 time: 7.179437875747681
myStack2 time: 8.115821123123169

可以看到方案一最节省空间,方案二时间效率最高,方案三在特殊要求的时候例如要求使用一个栈来实现。

喜欢 (0)
取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦


Warning: Use of undefined constant PRC - assumed 'PRC' (this will throw an Error in a future version of PHP) in C:\inetpub\wordpress\wp-content\themes\XHBlog\comments.php on line 17
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址