关于栈的算法

栈是什么?

之前学过队列,是先进先出,而栈则是先进后出,栈就像一个弹夹,先装入的子弹,后被打出来

python中的栈的使用

python中没有栈这种数据结构,我们可以直接使用list模拟栈的行为

栈的时间复杂度

  1. 插入:O(1),栈只能从最上面插入元素
  2. 查询: O(N),查询栈中的的某一个元素,最坏情况需要全部遍历
  3. 删除: O(1),栈每次只能删除最上面的那个元素
  4. 访问: O(1),栈访问元素只能访问最上面的那个元素

关于栈的算法

  1. 20有效的括号

    这道题可以使用栈的方式去解答:
    括号分为左右两个部分,我们可以只看左边的或者右边的那部分,把它压入栈中。我这里是以左边为例,如果巡检到右边的括号,则从栈中弹出最上面的那个元素与巡检到的这个右边的括号进行匹配,如果匹配,则继续循环,如果比匹配则返回False
    方法一:
class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        if len(s) % 2 != 0:
            return False
        for i in s:
            if i in "([{":
                stack.append(i)
            else:
                if not stack:
                    return False
                left = stack.pop()
                now_str = left + i
                if now_str not in "()[]{}":
                    return False
        if len(stack) == 0:
            return True
        return False

方法一代码感觉有些冗余,所以优化后就有了方法二
方法二:

class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        maps = {
            "(":")",
            "[":"]",
            "{":"}"
        }
        if len(s) % 2 != 0:
            return False
        for i in s:
            if maps.get(i):
                stack.append(i)
            else:
                if not stack:
                    return False
                if maps.get(stack.pop()) != i:
                    return False
        return len(stack) == 0

这是我想出来的几个方法,官方的方案是:

class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2 == 1:
            return False
        
        pairs = {
            ")": "(",
            "]": "[",
            "}": "{",
        }
        stack = list()
        for ch in s:
            if ch in pairs:
                if not stack or stack[-1] != pairs[ch]:
                    return False
                stack.pop()
            else:
                stack.append(ch)
        
        return not stack

参考其他人的方案:
下面是其他几个大佬的解法
第一个:这个是这些方法中耗时最短的

class Solution:
    def isValid(self, s: str) -> bool:
        dic = {'{': '}',  '[': ']', '(': ')', '?': '?'}
        stack = ['?']
        for c in s:
            if c in dic: stack.append(c)
            elif dic[stack.pop()] != c: return False 
        return len(stack) == 1

第二个:这个耗时较多,但是思路很新奇

class Solution:
    def isValid(self, s):
        while '{}' in s or '()' in s or '[]' in s:
            s = s.replace('{}', '')
            s = s.replace('[]', '')
            s = s.replace('()', '')
        return s == ''
  1. 496下一个更大值
  • 传统解法

    我的最开始的想法是,既然nums1是nums2的子集,并且这两个数组中的元素都不会重复,那么我可以直接遍历nums1获取到元素后再在nums2中查询这个值和它的下标。最后判断这个值后面是否有更大的值,如果有,则添加到一个数组中,并且跳出循环。如果没有则添加-1到数组中
class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        arr = []
        for i in nums1:
            n = None
            for j, v in enumerate(nums2):
                if i == v:
                    n = j
                if isinstance(n, int) and j >= n:
                    if i < v:
                        arr.append(v)
                        break
            else:
                arr.append(-1)
        return arr

这个属于传统思路的解法,时间复杂度较高

  • 使用栈的解法
    这里有两个方案,官方答案是使用一个字典+栈组合搞定。还有个是使用两个栈配后解决。
    官方的答案:
    这里的思路是栈顶元素要么是最大值,要么就是-1。在stack and num >= stack[-1]的判断之后,如果满足stack不为空,且当前元素num大于或等于栈顶元素,则说明当前栈顶元素不满足条件,所以会被从栈中移除。一直循环,直到完全满足条件为止或者stack为空。res[num] = stack[-1] if stack else -1通过while的筛选后,如果stack有值,那么栈顶元素肯定大于num,如果stack不存在,那么num就没有最大值,所以为-1。[res[num] for num in nums1]最后通过字典直接可以取值的方式,获取到每个num对应的关联值即可。
    其实这总结就是使用stack存储当前num所能对应的下一个最大值,然后把关系存储到res这个字典中,最后再循环nums1把这些需要用到的关系从res中取出放入一个新的数组中即可
class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        res = {}
        stack = []
        for num in reversed(nums2):
            while stack and num >= stack[-1]:
                stack.pop()
            res[num] = stack[-1] if stack else -1
            stack.append(num)
        return [res[num] for num in nums1]

两个栈进行配后解决的思路是:
因为栈是先进后出的一种数据结构,所以可以用它来对nums2进行操作,边查询边删除,而被删除的元素会被压入另一个辅助的栈中,每次比较完成,使用辅助栈恢复nums2,保证数据完整性。

代码暂时没些,先写明思路,后面补充代码
posted @ 2022-08-09 00:07  影梦无痕  阅读(49)  评论(0)    收藏  举报