2020/06/14 rank 1173/3803 ac 2
引言
状态不是很好,这周只a了两道题,思路不畅。
制作m束花的天数
首先想到采用二分的方法,核心在于注意到题目的解具有单调性,也就是说,在第i
天可以,则在之后的第i+1
天也是都可以的。
class Solution:
def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
## 二分的方法
right = max(bloomDay)
left = 1
def valid(mid):
flower = 0
need = m
for i in range(len(bloomDay)):
if bloomDay[i]<=mid:
flower += 1
else:
need -= flower//k
flower = 0
need -= flower//k
return need<=0
while left<=right:
mid = left+(right-left)//2
if valid(mid):
right = mid-1
else:
left = mid+1
if left>max(bloomDay):
return -1
return left
另外一个方法是我在答题时候的思路,但是考场上没有能做出来。也就是利用字典,维护区间的算法。其实很类似于并查集。利用两个字典维护每一个连续数组的左右边界。
需要注意,字典r
是维护了一个右侧连续数组的右端点,l
维护了一个左侧连续数组的左端点。
class Solution(object):
def minDays(self, bloomDay, m, k):
"""
:type bloomDay: List[int]
:type m: int
:type k: int
:rtype: int
"""
## 区间合并的算法
days = []
for i in range(len(bloomDay)):
days.append([bloomDay[i], i])
days.sort(key = lambda x:x[0])
r = {}
l = {}
sum_ = 0
def get(left, right):
return (right-left+1)//k
for day,index in days:
if index-1 in l and index+1 in r:
sum_ = sum_ - get(l[index-1],index-1) - get(index+1,r[index+1]) + get(l[index-1],r[index+1])
## 这一步的更新需要注意,更改最左边位置的右界限和最右边位置的左边界。
r[l[index-1]] = r[index+1]
l[r[index+1]] = l[index-1]
elif index-1 in l:
sum_ = sum_ - get(l[index-1],index-1) + get(l[index-1],index)
r[l[index-1]] = index
l[index] = l[index-1]
elif index+1 in r:
sum_ = sum_- get(index+1,r[index+1]) + get(index,r[index+1])
l[r[index+1]] = index
r[index] = r[index+1]
else:
r[index] = index
l[index] = index
sum_ += get(index,index)
print(sum_)
if sum_ >=m:
return day
return -1
树上倍增
树上倍增算法
class TreeAncestor:
def __init__(self, n: int, parent: List[int]):
self.cols = 20 # log(50000) < 20
self.dp = [[-1] * self.cols for _ in range(n)]
for i in range(n):
self.dp[i][0] = parent[i]
# 动态规划设置祖先, dp[node][j] 表示 node 往前推第 2^j 个祖先
for j in range(1, self.cols):
for i in range(n):
if self.dp[i][j-1] != -1:
self.dp[i][j] = self.dp[self.dp[i][j-1]][j-1]
return
def getKthAncestor(self, node: int, k: int) -> int:
for i in range(self.cols - 1, -1, -1):
if k & (1 << i):
node = self.dp[node][i]
if node == -1:
break
return node
# Your TreeAncestor object will be instantiated and called as such:
# obj = TreeAncestor(n, parent)
# param_1 = obj.getKthAncestor(node,k)