6.1力扣栈 期待offer的儿童节礼物!

56. 合并区间
在这里插入图片描述

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        if not intervals:
            return intervals
        intervals=sorted(intervals,key=lambda x:(x[0],x[1]))
        res=[]
        res.append(intervals[0])
        for i in range(1,len(intervals)):
            if intervals[i][0]>res[-1][1]:
                res.append(intervals[i])
            else:
                left=min(res[-1][0],intervals[i][0])
                right=max(res[-1][1],intervals[i][1])
                res.pop()
                res.append([left,right])
        return res

986. 区间列表的交集
在这里插入图片描述
假设拥有最小末端点的区间是 A[0],
在数组 B 的区间中, A[0] 只可能与数组 B 中的至多一个区间相交。(如果 B 中存在两个区间均与 A[0] 相交,那么它们将共同包含 A[0] 的末端点,但是 B 中的区间应该是不相交的,所以存在矛盾)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
例如 如果 A[0] 拥有最小的末端点,那么它只可能与 B[0] 相交。然后我们就可以删除区间 A[0],因为它不能与其他任何区间再相交了。
相似的,如果 B[0] 拥有最小的末端点,那么它只可能与区间 A[0] 相交,然后我们就可以将 B[0] 删除,因为它无法再与其他区间相交了。
我们用两个指针 i 与 j 来模拟完成删除 A[0] 或 B[0] 的操作

class Solution:
    def intervalIntersection(self, A: List[List[int]], B: List[List[int]]) -> List[List[int]]:
        res=[]
        i,j=0,0
        while i<len(A) and j<len(B):
            left=max(A[i][0],B[j][0])
            right=min(A[i][1],B[j][1])
            if left<=right:
                res.append([left,right])
            if A[i][1]<B[j][1]:
                i+=1
            else:
                j+=1
        return res

385. 迷你语法分析器
在这里插入图片描述
在这里插入图片描述

#class NestedInteger:
#    def __init__(self, value=None):
#        """
#        If value is not specified, initializes an empty list.
#        Otherwise initializes a single integer equal to value.
#        """
#    def add(self, elem):
#        """
#        Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
#        :rtype void
#        """


class Solution:
    def deserialize(self, s: str) -> NestedInteger:
        if s[0]!='[':
            return NestedInteger(int(s))
        num,sign,stack=0,1,[]
        is_num=False
        for c in s:
            if c.isdigit():
            #计算十进制数字
                num=num*10+int(c)
                is_num=True
            elif c=='-':
                sign=-1
            elif c=='[':
           # 栈append一个空的NestedInteger对象
                stack.append(NestedInteger())
            elif c==']' or c==',':
                if is_num:
                    cur_list=stack.pop()
                    cur_list.add(NestedInteger(sign*num))
                    stack.append(cur_list)
                num,sign,is_num=0,1,False
                #嵌套列表
                if c==']' and len(stack)>1:
                    cur_list=stack.pop()
                    #加到上一个
                    stack[-1].add(cur_list)
        return stack[0]

71. 简化路径
在这里插入图片描述
在这里插入图片描述
把当前目录压入栈中,遇到…弹出栈顶,最后返回栈中元素.

class Solution:
    def simplifyPath(self, path: str) -> str:
        path=path.split('/')
        res=[]
        for item in path:
        #返回上一级则弹出栈顶
            if item=='..':
                if res:
                    res.pop()
            elif item and item!='.':
                res.append(item)
        return '/'+'/'.join(res)

848. 字母移位
在这里插入图片描述
因为对第 i 个字母及后面字母的移位都会导致第 i 个字母移位,所以第 i 个字母共移位 shifts[i] + shifts[i+1] + … + shifts[shifts.length - 1] 次。
假设第 i 个字母移位 X 次,那么第 i + 1 个字母移位 X - shifts[i] 次。
当 i 增加时,令 X -= shifts[i] 计算下一个字母的移位次数。

class Solution:
    def shiftingLetters(self, S: str, shifts: List[int]) -> str:
        #对第i个字母及其后面字母的移位都会影响第I个字母移位,后面每个字母移位都比当前字母移位少shifts[i]
        x=sum(shifts)%26
        res=[]
        for i,c in enumerate(S):
            idx=ord(c)-ord('a')
            res.append(chr(ord('a')+(idx+x)%26))
            #下一个字母的移位次数
            x=(x-shifts[i])%26
        return ''.join(res)

58. 最后一个单词的长度
在这里插入图片描述

class Solution:
    def lengthOfLastWord(self, s: str) -> int:
        return len(s.strip(' ').split(' ')[-1])
class Solution:
    def lengthOfLastWord(self, s: str) -> int:
        if not s:
            return 0
        count = 0
        flag = 0
        for i in s[::-1]:
        #最后面的空格,后面没有数字
            if i is " " and flag == 0:
                continue
            if i is not " ":
                count += 1
                flag = 1
            else:
                break
        return count

816. 模糊坐标
在这里插入图片描述
在这里插入图片描述
itertools.product:类似于求多个可迭代对象的笛卡尔积
主要是判断特殊情况
#1:在n个数中间加逗号
#2:给第一步产生的字符串加小数点(并判断合法),下面是判断规则
if S == “”: return []
if S == “0”: return [S]
if S == “0XXX0”: return []
if S == “0XXX”: return [“0.XXX”]
if S == “XXX0”: return [S]
return [S, “X.XXX”, “XX.XX”, “XXX.X”…]

class Solution:
    def ambiguousCoordinates(self, S: str) -> List[str]:
        #去掉括号
        S=S[1:-1]
        def f(s):
            #首尾都为0,字符串不符合要求
            if not s or(len(s)>1 and s[0]=='0' and s[-1]=='0'):
                return []
            if s=='0':
                return [s[0]]
            # 第一位为0,小数点只能加到0后面
            if len(s)>1 and s[0]=='0':
                return [s[0]+'.'+s[1:]]
                #最后一位为0,且长度大于1,只能返回整个字符串,无法加小数点
            if len(s)>1 and s[-1]=='0':
                return [s]
            return [s]+ [s[:i]+'.'+s[i:] for i in range(1,len(s))]
            #分割数字
        res=[]
        #可以加,的地方
        for i in range(1,len(S)):
            #前后组合
            for x,y in itertools.product(f(S[:i]),f(S[i:])):
                res.append('(%s, %s)'%(x,y))
        return res

1130. 叶值的最小代价生成树
在这里插入图片描述
中序遍历就决定了arr数组(0…n-1)里的第k位元素的所有左边元素(包括它自己)都在左子树里,而其右边元素都在右子树里,而此时左右两边子树分别选出最大值的乘积就是此时的根,也就是题目中说的非叶节点

中序遍历,叶子节点从左到右,每个点都会发起组合,组合可能是和左边的也可能是和右边的组合,同时小的那个元素就不再需要了,我们只看大的那个元素可能还会和别的值相乘。所以大的元素保存下来
每个非叶结点都是左右子树叶节点中最大值的乘积,所以每次只消掉小的数,每次用相邻的两个较小的叶节点合成中间节点,最终可以得到最小代价生成树。
用单调递减栈保存
如果栈不空,剩下的叶子节点要乘起来
时间复杂度为 O(N)

class Solution:
    def mctFromLeafValues(self, arr: List[int]) -> int:
        stack=[float('inf')]
        res=0
        for i in arr:
        #单调递减栈,消除小的元素
            while stack and stack[-1]<=i:
                mid=stack.pop()
                res+=mid*(min(stack[-1],i))
            stack.append(i)
        #因为有哨兵元素,长度等于2的时候弹出
        while len(stack)>2:
        #栈不为空,要把叶子结点相乘获得根
            res+=stack.pop()*stack[-1]
        return res

682. 棒球比赛
在这里插入图片描述在这里插入图片描述

class Solution:
    def calPoints(self, ops: List[str]) -> int:
        stack=[]
        for c in ops:
            #负数对isdigit是False
            if (c.startswith('-') and c[1:] or c).isdigit():
                stack.append(int(c))
            elif stack and c=='C':
                stack.pop()
            elif stack and c=='D':
                stack.append(2*stack[-1])
            elif len(stack)>1 and c=='+':
                stack.append(stack[-1]+stack[-2])
        return sum(stack)

856. 括号的分数
在这里插入图片描述
在这里插入图片描述
我们用一个栈来维护当前所在的深度,以及每一层深度的得分。当我们遇到一个左括号 ( 时,我们将深度加一,并且新的深度的得分置为 0。当我们遇到一个右括号 ) 时,我们将当前深度的得分乘二并加到上一层的深度。这里有一种例外情况,如果遇到的是 (),那么只将得分加一。

class Solution:
    def scoreOfParentheses(self, S: str) -> int:
        stack=[0]
        for i in S:
            if i=='(':
                stack.append(0)
            elif i==')':
                v=stack.pop()
                stack[-1]+=max(2*v,1)
        return stack[0]

第二种写法:
https://leetcode-cn.com/problems/score-of-parentheses/solution/kan-bu-dong-bie-ren-de-ti-jie-zi-ji-you-xie-liao-y/
在这里插入图片描述

class Solution:
    def scoreOfParentheses(self, S: str) -> int:
        stack=[]
        for i in S:
            if i=='(':
                stack.append(i)
            elif i==')':
                #() 得1分
                if stack[-1]=='(':
                    stack.pop()
                    stack.append(1)
                #(1,2。。):(1+2)*2
                elif stack[-1]!='(':
                    tmp=0
                    while stack[-1]!='(':
                        a=stack.pop()
                        tmp+=a
                    stack.pop()
                    stack.append(2*tmp)
        return sum(stack)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值