leetcode第143场周赛总结

leetcode第143场周赛总结

第一题:1104.分糖果II

排排坐,分糖果。我们买了一些糖果 candies,打算把它们分给排好队的 n = num_people 个小朋友。

给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类推,直到给最后一个小朋友 n 颗糖果。

然后,我们再回到队伍的起点,给第一个小朋友 n + 1 颗糖果,第二个小朋友 n + 2 颗,依此类推,直到给最后一个小朋友 2 * n颗糖果。

重复上述过程(每次都比上一次多给出一颗糖果,当到达队伍终点后再次从队伍起点开始),直到我们分完所有的糖果。注意,就算我们手中的剩下糖果数不够(不比前一次发出的糖果多),这些糖果也会全部发给当前的小朋友。

返回一个长度为 num_people、元素之和为 candies 的数组,以表示糖果的最终分发情况(即 ans[i] 表示第 i 个小朋友分到的糖果数)。

示例1:
在这里插入图片描述
示例2:
在这里插入图片描述
提示:

1 <= candies <= 10^9
1 <= num_people <= 1000

分析:一开始我看到提示条件感觉这个数据量应该很大,就觉得暴力法去做的话应该会超时,但是其实这题是简单题,暴力法就能过…而且从最后提交通过的时间来看,测试用例并不是很大。

class Solution:
    def distributeCandies(self, candies: int, num_people: int) -> List[int]:
        ans = [0] * num_people
        start = 1
        while candies > 0:
            for i in range(num_people):
                if candies >= start:
                    ans[i] += start
                    candies -= start
                    start += 1
                else:
                    ans[i] += candies
                    return ans
第二题:1103二叉树寻路

在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。
如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记;
而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。
在这里插入图片描述
给你树上某一个节点的标号 label,请你返回从根节点到该标号为 label 节点的路径,该路径是由途经的节点标号所组成的。

示例1:

输入:label = 14
输出:[1,3,4,14]

示例2:

输入:label = 26
输出:[1,2,6,10,26]

提示:

1 <= label <= 10^6

分析:比较简单直接的一个想法就是先按照题目描述规则建立这颗二叉树的节点标记的序列,然后再从后往前依次找到路径的标记。

class Solution:
    def pathInZigZagTree(self, label: int) -> List[int]:
        tree=[[1]]
        d=cur=num=1
        while cur<label:
            num*=2
            d=(d+1)%2
            new=list(range(cur+1,cur+num+1))
            cur+=num
            if d:
                tree.append(new)
            else:
                tree.append(new[::-1])
        print(tree)
        path=[]
        curid=tree[-1].index(label)
        for rowid in range(len(tree)-1,-1,-1):
            path.append(tree[rowid][curid])
            curid//=2
        return path[::-1]
第三题:1105填充书架

附近的家居城促销,你买回了一直心仪的可调节书架,打算把自己的书都整理到新的书架上。
你把要摆放的书 books 都整理好,叠成一摞:从上往下,第 i 本书的厚度为 books[i][0],高度为 books[i][1]。
按顺序 将这些书摆放到总宽度为 shelf_width 的书架上。
先选几本书放在书架上(它们的厚度之和小于等于书架的宽度 shelf_width),然后再建一层书架。重复这个过程,直到把所有的书都放在书架上。
需要注意的是,在上述过程的每个步骤中,摆放书的顺序与你整理好的顺序相同。 例如,如果这里有 5 本书,那么可能的一种摆放情况是:第一和第二本书放在第一层书架上,第三本书放在第二层书架上,第四和第五本书放在最后一层书架上。
每一层所摆放的书的最大高度就是这一层书架的层高,书架整体的高度为各层高之和。
以这种方式布置书架,返回书架整体可能的最小高度。

示例:

输入:books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelf_width = 4
输出:6
解释:
3 层书架的高度和为 1 + 3 + 2 = 6 。
第 2 本书不必放在第一层书架上。
在这里插入图片描述

分析:关键在于需要按顺序来摆放书。每一层摆放的书的宽度之和不能超过书架的宽度,在这个约束下,每本书选择摆在哪一层既取决于它前面的书又取决于它后面的书,所以此题适合用动态规划来解决,从前往后遍历这些书,对于当前遍历的书当作最后一本来考虑,考虑将从它往前的这些书中宽度之和不超过书架宽度的这些书放在一层的所有情况,去更新目前书架的总高度,这样就能得到当前书架的最低高度。这样我们就可以得到将每一本书作为最后一本书时的最小高度,所以当后面再有新的书加入的时候,我们就能用这些最小高度去更新最新的最小高度。

class Solution:
    def minHeightShelves(self, books: List[List[int]], shelf_width: int) -> int:
        from math import inf
        minheight = {0: 0}
        nbooks = len (books)
        for n in range (1, nbooks+1):
            # decide height for first n books
            minheight[n] = inf
            maxh = 0
            maxw = 0
            for i in range (1, n+1):
                maxh = max (maxh, books[n-i][1])
                maxw += books[n-i][0]
                if maxw <= shelf_width:
                    minheight[n] = min (minheight[n], maxh + minheight[n - i])
                else:
                    break
        return minheight[nbooks]
第四题:1106. 解析布尔表达式

给你一个以字符串形式表述的 布尔表达式(boolean) expression,返回该式的运算结果。
有效的表达式需遵循以下约定:
“t”,运算结果为 True
“f”,运算结果为 False
“!(expr)”,运算过程为对内部表达式 expr 进行逻辑 非的运算(NOT)
“&(expr1,expr2,…)”,运算过程为对 2 个或以上内部表达式 expr1, expr2, … 进行逻辑 与的运算(AND)
“|(expr1,expr2,…)”,运算过程为对 2 个或以上内部表达式 expr1, expr2, … 进行逻辑 或的运算(OR)

示例1:

输入:expression = “!(f)”
输出:true

示例2:

输入:expression = “|(f,t)”
输出:true

示例3:

输入:expression = “|(&(t,f,t),!(t))”
输出:false

分析:每个与或非(&,|,!)符号后面都一定跟有一个由圆括号括起来的表达式,整个式子的运算需要满足先后顺序,即由圆括号决定的运算顺序,因此可以利用栈来实现。可以考虑先把expression整理成我们方便处理的形式,即依据括号的关系将expression根据圆括号决定的运算顺序存入栈中,然后再根据这个栈依次进行运算即可。

def booleval (expr):
    if type(expr) is list:
        oper = expr[0]
        if oper == '!':
            return not (booleval (expr[1]))
        elif oper == '&':
            return all (booleval (subexpr) for subexpr in expr[1:])
        elif oper == '|':
            return any (booleval (subexpr) for subexpr in expr[1:])
    else:
        return {'t':True, 'f':False} [expr]

class Solution:
    def parseBoolExpr(self, expression: str) -> bool:
        stack = [[]]
        for char in expression:
            if char in 'tf':
                stack[-1].append (char)
            elif char == ')':
                stack[-2].append (stack[-1])
                stack.pop ()
            elif char in '!&|':
                stack.append ([char])
        return booleval (stack[-1][-1])
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值