这次的题目相对来说比较简单,终于在一个半小时内做完了。。。。
比赛地址链接:https://leetcode-cn.com/contest/weekly-contest-143/
第一题 分糖果Ⅱ
题目大意:
一共num_people个小朋友,给小朋友们分糖果,从第一个小朋友开始分1,2,...,num_people,分到最后一个小朋友时,糖果还没分完,再从第一个小朋友开始分num_people+1个,每次糖果加一,分到糖果不够分时,把剩下所有的糖果分给该拿糖果的那个小朋友。
解题思路:
利用求和公式,看发一轮糖果需要用掉多少糖果,可以发多少轮,最后把剩下的糖果再分一下即可
代码如下:
class Solution:
def distributeCandies(self, candies: int, num_people: int) -> List[int]:
candy_list = [0 for i in range(0,num_people)]
x = 1
round = 0
#糖果够分几轮
while candies >= (num_people + 2 * x - 1) * num_people // 2:
candy_list[0] += x
candies -= (num_people + 2 * x - 1) * num_people // 2
round += 1
x += num_people
for i in range(1, num_people):
candy_list[i] = candy_list[i - 1] + round
#分剩余的糖果
for i in range(0, num_people):
if candies > x:
candy_list[i] += x
candies -= x
x += 1
else:
candy_list[i] += candies
break
return candy_list
第二题 二叉树寻路
题目大意:
一颗完全二叉树,根节点算第一层,奇数层从左到右编号,偶数层从右到左编号,给你一个节点的编号,给出从根节点到该节点的路径。
解题思路:
如果是一颗正常的完全二叉树,他的父节点的值即为自己节点的值除以2,所以我们只需要看该节点对应到现在新的这个二叉树上的值即可。
代码如下:
class Solution:
def pathInZigZagTree(self, label: int) -> List[int]:
level = 1
s = 2
#计算层数
while s - 1 < label:
level += 1
s *= 2
ans_list = []
#如果层数是偶数层,则变成正常二叉树对应的值
if level % 2 == 0:
label = s - label + s // 2 - 1
while level > 0:
#如果层数是奇数层,则即为该值
if level % 2 == 1:
ans_list.append(label)
else:
#若为偶数层,则变成之字二叉树对应的值
ans_list.append(s - label + s // 2 - 1)
label = label // 2
s = s // 2
level -= 1
return ans_list[::-1]
第三题 填充书架
题目大意:
有一堆书,第i本书的厚度为books[i][0],高度为books[i][1],现将这些书按照books中的顺序放在宽度为shelf_width
的书架上,每层所摆放的书的最大高度就是这一层书架的层高,宽度为这一层书的所有宽度之和,书架整体的高度为各层高之和。
解题思路:
这题是这次比赛里相对难一点的题了,书最多有1000本,书架的宽度最大为1000。因为题目要求必须按照输入给定的顺序来放,故可以考虑从当前这本书到之前的某一本书的这些小于等于shelf_width
宽度的书放在同一层。利用动态规划的思想,设f[i]为从1到i本书一共用了多少高度,f[i] = min(f[i],f[j]+ 从i+1到j的书的最大高度) (i+1 到 j 的书的宽度和小于等于shelf_width
),时间复杂度为o(n^2),n为书的数目。
代码如下:
class Solution:
def minHeightShelves(self, books: List[List[int]], shelf_width: int) -> int:
ans = [999999999 for i in range(0, len(books) + 1)]
ans[0] = 0
for i in range(0, len(books)):
maxlen = books[i][1]
width_now = books[i][0]
for j in range(i , -1, -1):
ans[i + 1] = min(ans[i + 1], ans[j] + maxlen)
if j > 0:
width_now += books[j - 1][0]
maxlen = max(maxlen, books[j - 1][1])
if width_now > shelf_width:
break
return ans[len(books)]
第四题 解析表达式
题目大意:
给你一个以字符串形式表述的 布尔表达式(boolean) expression
,返回该式的运算结果。
解题思路:
因为一次运算的运算数都在括号内,故可以每次遇到右括号就执行一次运算。使用两个栈,一个栈存放运算符,一个栈存放运算数和括号。每次遇到右括号时,将运算数弹出直至遇到左括号,运算符栈弹出一个运算符,进行运算后,再压入到运算数栈中。运算结束后,将运算数栈的最后一个内容弹出即可。
代码如下:
class Solution:
def parseBoolExpr(self, expression: str) -> bool:
ysf = []
zhi = []
for each in expression:
if each in ['!','|','&']:
ysf.append(each)
elif each in ['(','t','f']:
if each == 't':
each = True
elif each == 'f':
each = False
zhi.append(each)
elif each == ')':
#弹出一个运算符
nowysf = ysf.pop()
#计算运算后的值
yszhi = None
nowzhi = zhi.pop()
while nowzhi != '(':
if yszhi == None:
yszhi = nowzhi
elif nowysf == '&':
yszhi = nowzhi and yszhi
elif nowysf == '|':
yszhi = nowzhi or yszhi
nowzhi = zhi.pop()
if nowysf == '!':
yszhi = not yszhi
#将运算后的值压入到运算数栈中
zhi.append(yszhi)
return zhi.pop()