LeetCode-栈-Hard

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




42.trapping-rain-water 接雨水

解题思路:
保留左右两边的值 中间的按照最高点灌满
假设让水从左侧流出 如果左侧的比本地的要小l[i]>l[i-1] 则水减少至左侧或者本地的柱子高度max(height[i],l[i-1])
从左到右检查一遍后 从右到左在检查一遍

def trap(height):
    """
    :type height: List[int]
    :rtype: int
    [0,1,0,2,1,0,1,3,2,1,2,1]
    """
    m = max(height)
    if len(height)<3:
        return 0
    l = [height[0]]+[m]*(len(height)-2)+[height[-1]]
    def check(l,ori):
        for i in range(1,len(l)):
            if l[i]>l[i-1]:
                l[i] = max(height[i],l[i-1])
        return l
    l=check(l,height)
    l.reverse()
    l = check(l,height.reverse())
    l.reverse()
    s =0
    for i in range(len(height)):
        s += l[i]-height[i]
    print(s)

84.largest-rectangle-in-histogram 柱状图中最大的矩形

解题思路:
1.主要是超时问题
2.使用一个list来保存数值的位置
遍历heights:
如果栈为空或者当前值大于栈顶位置的值 则将这个位置放入栈中
如果当前值小于等于栈顶位置值 将栈顶的位置pop 计算这个值h能够产生的矩形面积
此时会用到pop后的栈顶位置posl[-1] 是h左边的边界 则面积为(i-posl[-1]-1)*h
开始时加入0 对最后的栈中情况进行处理

def largestRectangleArea1(heights):
    """
    :type heights: List[int]
    :rtype: int
    """
    if not heights:
        return 0
    
    def check(h):
        cur=0
        ans=cur
        for i in heights:
            if i>=h:
                cur+=1
            else:
                ans = max(ans,cur)
                cur=0
        ans = max(ans,cur)
        return ans*h
    
    ret = 0
    for i in set(heights):
        tmp=check(i)
        ret = max(ret,tmp)
    return ret


def largestRectangleArea(heights):
    """
    :type heights: List[int]
    :rtype: int
    
    """
    posl =[]
    ret = 0
    
    heights.append(0)
    n = len(heights)
    for i in range(n):
        if not posl or heights[i] > heights[posl[-1]]:
            posl.append(i)
        else:
            while posl and heights[i] <= heights[posl[-1]]:
                h = heights[posl[-1]]
                posl.pop()
                if not posl:
                    l = i
                else:
                    l = i - posl[-1]-1
                ret = max(ret, h * l)
            posl.append(i)
    return ret

85.maximal-rectangle 最大矩形

解题思路:
可以利用84中的方法
每一层网上看都能转换成84题中直方图求举证大小
每一层如果该层某一位置为0 则无论往上是否有1 改处在直方图中的值为0

def maximalRectangle(matrix):
    """
    :type matrix: List[List[str]]
    :rtype: int
    """
    x = len(matrix)
    ret =0
    if x==0:
        return 0
    y = len(matrix[0])
    
    def largestRectangleArea(heights):
        posl =[]
        ret = 0
        
        heights.append(0)
        n = len(heights)
        for i in range(n):
            if not posl or heights[i] > heights[posl[-1]]:
                posl.append(i)
            else:
                while posl and heights[i] <= heights[posl[-1]]:
                    h = heights[posl[-1]]
                    posl.pop()
                    if not posl:
                        l = i
                    else:
                        l = i - posl[-1]-1
                    ret = max(ret, h * l)
                posl.append(i)
        return ret
            
    
    for i in range(x):
        height=[]
        for j in range(y):
            n = 0
            tmpi = i
            while matrix[tmpi][j]=="1" and tmpi>=0:
                n+=1
                tmpi-=1
            height.append(n)
        ret = max(ret,largestRectangleArea(height))
    return ret

145.binary-tree-postorder-traversal 二叉树的后序遍历

解题思路:
后序遍历:左右根
取值时根右左,结果倒序

class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def postorderTraversal(root):
    """
    :type root: TreeNode
    :rtype: List[int]
    """
    ret =[]
    stack=[]
    if not root:
        return ret
    
    stack.append(root)
    while stack:
        v = stack.pop()
        if v.left:
            stack.append(v.left)
        if v.right:
            stack.append(v.right)
        
        ret.append(v.val)
    ret.reverse()
    return ret

224.basic-calculator 基本计算器

解题思路:
遍历str 放入stack中 同时将数字整合到一起 如果遇到‘)’ 则开始往前寻找’(’ 将经过的数值计算
非负整数 所以最后stack中第一个数必定为正整数 使用+

def calculate(s):
    """
    :type s: str
    :rtype: int
    """
    stack=[]
    ret = 0
    numpre =""
    for i in s:
        if i==" ":
            continue
        if i!=")":
            if i.isdigit():
                numpre +=i
            else:
                if numpre!="":
                    stack.append(int(numpre))
                    numpre=""
                stack.append(i)
        else: 
            if numpre!="":
                stack.append(int(numpre))
                numpre=""
            tmp = stack.pop()
            pre = 0
            res = 0
            while tmp!="(":
                if tmp=="+":
                    res +=pre
                elif tmp=="-":
                    res -=pre
                else:
                    pre = int(tmp)
                tmp = stack.pop()
            res+=pre
            stack.append(res)
    if numpre!="":
        stack.append(int(numpre))
    action = "+"
    stack.append("+")
    for i in stack:
        if i in ("-","+"):
            if action=="+":
                ret +=pre
            else:
                ret -= pre
            action =i
        else:
            pre = i
    return ret

316.remove-duplicate-letters 去除重复字母

解题思路:
使用dic记录所有字母出现的次数
当往stack中添加字母x时,判断在他前面的字母是否比x大 而且在后面任然会出现
如果成立将这个字母从stack去除 继续往前判断
判断结束后 将x加入stack中 此时有的字母结果为resultset
当有字母已在前面放入了stack并保留了下来(在set内) 则可以不需再判断

def removeDuplicateLetters(s):
    """
    :type s: str
    :rtype: str
    """
    dic = {}
    for c in s:
        dic[c] = dic.get(c,0)+1
    resultSet = set()
    stack = list()
    for c in s:
        dic[c] -= 1
        if c in resultSet:
            continue
        while stack and stack[-1] > c and dic[stack[-1]]:
            stack.pop()
        stack.append(c)
        resultSet = set(stack)
    return ''.join(stack)

猜你喜欢

转载自blog.csdn.net/zkt286468541/article/details/85053808
今日推荐