记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
-
-
- [3/9 3129. 找出所有稳定的二进制数组 I](#3/9 3129. 找出所有稳定的二进制数组 I)
- [3/10 3130. 找出所有稳定的二进制数组 II](#3/10 3130. 找出所有稳定的二进制数组 II)
- [3/11 1009. 十进制整数的反码](#3/11 1009. 十进制整数的反码)
- [3/12 3600. 升级后最大生成树稳定性](#3/12 3600. 升级后最大生成树稳定性)
- [3/13 3296. 移山所需的最少秒数](#3/13 3296. 移山所需的最少秒数)
- [3/14 1415. 长度为 n 的开心字符串中字典序第 k 小的字符串](#3/14 1415. 长度为 n 的开心字符串中字典序第 k 小的字符串)
- [3/15 1622. 奇妙序列](#3/15 1622. 奇妙序列)
-
3/9 3129. 找出所有稳定的二进制数组 I
每个长度为limit+1的子数组必定包含0和1
dp0[i][j]表示已经放入i个0和j个1 且最后一个为0的数目
dp1[i][j]表示已经放入i个0和j个1 且最后一个为1的数目
dp0[i][j] 可以由dp0[i-1][j] dp1[i-1][j]增加一个0得来
但对于dp0[i-1][j]中 如果已经有连续limit个0则不行 需要减去dp1[i-1-limit][j]
dp1同理
python
def numberOfStableArrays(zero, one, limit):
"""
:type zero: int
:type one: int
:type limit: int
:rtype: int
"""
MOD=10**9+7
dp = [[[0,0] for _ in range(one+1)] for _ in range(zero+1)]
for i in range(min(zero,limit)+1):
dp[i][0][0]=1
for j in range(min(one,limit)+1):
dp[0][j][1]=1
for i in range(1,zero+1):
for j in range(1,one+1):
if i>limit:
dp[i][j][0] = dp[i-1][j][0]+dp[i-1][j][1]-dp[i-1-limit][j][1]
else:
dp[i][j][0] = dp[i-1][j][0]+dp[i-1][j][1]
dp[i][j][0] = (dp[i][j][0]+MOD)%MOD
if j>limit:
dp[i][j][1] = dp[i][j-1][0]+dp[i][j-1][1]-dp[i][j-1-limit][0]
else:
dp[i][j][1] = dp[i][j-1][0]+dp[i][j-1][1]
dp[i][j][1] = (dp[i][j][1]+MOD)%MOD
return (dp[zero][one][0]+dp[zero][one][1])%MOD
3/10 3130. 找出所有稳定的二进制数组 II
每个长度为limit+1的子数组必定包含0和1
dp0[i][j]表示已经放入i个0和j个1 且最后一个为0的数目
dp1[i][j]表示已经放入i个0和j个1 且最后一个为1的数目
dp0[i][j] 可以由dp0[i-1][j] dp1[i-1][j]增加一个0得来
但对于dp0[i-1][j]中 如果已经有连续limit个0则不行 需要减去dp1[i-1-limit][j]
dp1同理
python
def numberOfStableArrays(zero, one, limit):
"""
:type zero: int
:type one: int
:type limit: int
:rtype: int
"""
MOD=10**9+7
dp = [[[0,0] for _ in range(one+1)] for _ in range(zero+1)]
for i in range(min(zero,limit)+1):
dp[i][0][0]=1
for j in range(min(one,limit)+1):
dp[0][j][1]=1
for i in range(1,zero+1):
for j in range(1,one+1):
if i>limit:
dp[i][j][0] = dp[i-1][j][0]+dp[i-1][j][1]-dp[i-1-limit][j][1]
else:
dp[i][j][0] = dp[i-1][j][0]+dp[i-1][j][1]
dp[i][j][0] = (dp[i][j][0]+MOD)%MOD
if j>limit:
dp[i][j][1] = dp[i][j-1][0]+dp[i][j-1][1]-dp[i][j-1-limit][0]
else:
dp[i][j][1] = dp[i][j-1][0]+dp[i][j-1][1]
dp[i][j][1] = (dp[i][j][1]+MOD)%MOD
return (dp[zero][one][0]+dp[zero][one][1])%MOD
3/11 1009. 十进制整数的反码
一位一位判断 如果是0则加上base 如果是1则不加
base左移一位
n右移一位
直到n为0
返回ans
特殊处理n为0的情况
python
def bitwiseComplement(n):
"""
:type n: int
:rtype: int
"""
if n==0:
return 1
ans = 0
base = 1
while n>0:
if not n&1:
ans += base
base <<=1
n >>=1
return ans
3/12 3600. 升级后最大生成树稳定性
二分答案x(目标最小边权) 单调性:x可行则x-1也可行
前置判断: must边成环或所有边加入仍不连通则返回-1
二分上界: 有must边时为min(must边权) 否则为max(2*可选边权)
check(x): 并查集依次加入must边 权值>=x的可选边 升级后满足的可选边(w<x且2w>=x 消耗升级次数)
最终判断是否连通且升级次数<=k
python
def maxStability(n, edges, k):
"""
:type n: int
:type edges: List[List[int]]
:type k: int
:rtype: int
"""
must = []
opt = []
for u, v, w, m in edges:
if m == 1:
must.append((u, v, w))
else:
opt.append((u, v, w))
def find(pa, x):
while pa[x] != x:
pa[x] = pa[pa[x]]
x = pa[x]
return x
def union(pa, x, y):
rx, ry = find(pa, x), find(pa, y)
if rx == ry:
return False
pa[rx] = ry
return True
def connected(pa):
return len(set(find(pa, i) for i in range(n))) == 1
pa = list(range(n))
for u, v, w in must:
if not union(pa, u, v):
return -1
pa = list(range(n))
for u, v, w, m in edges:
union(pa, u, v)
if not connected(pa):
return -1
def check(x):
pa = list(range(n))
cnt = 0
for u, v, w in must:
union(pa, u, v)
for u, v, w in opt:
if w >= x:
union(pa, u, v)
for u, v, w in opt:
if w < x and 2 * w >= x and find(pa, u) != find(pa, v):
cnt += 1
if cnt > k:
return False
union(pa, u, v)
return connected(pa)
if must:
hi = min(w for u, v, w in must)
else:
hi = max(2 * w for u, v, w in opt) if opt else 0
lo, ans = 0, 0
while lo <= hi:
mid = (lo + hi) // 2
if check(mid):
ans = mid
lo = mid + 1
else:
hi = mid - 1
return ans
3/13 3296. 移山所需的最少秒数
二分 如果t秒能够移除 那么任何大于t的秒数也可以
对于当前秒数mid 判断是否能够降低mountainHeight
对于工人i 降低k高度 需要workerTimes[i](1+2+...+k) = workerTimes[i]k (k+1)/2 时间
在mid内 第i个工人最多降低满足workerTimes[i] (k*(k+1)/2) <= mid 的最大正整数kk = (sqrt(8*mid/wt + 1) - 1) / 2
python
def minNumberOfSeconds(mountainHeight, workerTimes):
"""
:type mountainHeight: int
:type workerTimes: List[int]
:rtype: int
"""
from math import isqrt
def check(mid):
total = 0
for wt in workerTimes:
k = (isqrt(8 * mid // wt + 1) - 1) // 2
total += k
if total >= mountainHeight:
return True
return False
lo, hi = 1, min(workerTimes) * mountainHeight * (mountainHeight + 1) // 2
while lo < hi:
mid = (lo + hi) // 2
if check(mid):
hi = mid
else:
lo = mid + 1
return lo
3/14 1415. 长度为 n 的开心字符串中字典序第 k 小的字符串
由题意可知 长度n的开心字符串 第一个位置有3种选择 第二个位置有2种选择 第三个位置有2种选择 以此类推
总共可以生成3*2^(n-1)个开心字符串 如果k大于这个数 则返回空字符串
从第一个位置判断 如果第一位位置是a 那么后续可以由2^(n-1)个开心字符串 如果k小于等于2^(n-1) 则第一位位置为a 否则第一位位置为b 以此类推
一位一位判断 直到判断到最后一位
python
def getHappyString(n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
cs=['a','b','c']
ans = []
if k>3*2**(n-1):
return ""
for i in range(n):
if len(ans)!=i:
break
cnt = 1<<(n-i-1)
for c in cs:
if ans and ans[-1]==c:
continue
if k<=cnt:
ans.append(c)
break
k-=cnt
return "".join(ans)
3/15 1622. 奇妙序列
执行加法 将所有值都统计到一起 当需要获取某个位置的值时 将所有值都加上inc 然后除以m 然后取模
所以在append时 将val先减去当前的加值 那么取出时加上加值能够满足
同样在乘法时 将val先除以当前的乘值 那么取出时乘以乘值能够满足
用add记录addall mul记录multall
addall(inc)时 add+inc
multall(m)时 mulm,并且add m
getIndex(idx)时 vals[idx]*mul+add
append(val)时 v=(val-add)/mul
python
MOD=10**9+7
class Fancy(object):
def __init__(self):
self.add = 0
self.mul = 1
self.vals = []
def append(self, val):
"""
:type val: int
:rtype: None
"""
self.vals.append((val-self.add)*pow(self.mul,MOD-2,MOD)%MOD)
def addAll(self, inc):
"""
:type inc: int
:rtype: None
"""
self.add += inc
def multAll(self, m):
"""
:type m: int
:rtype: None
"""
self.mul = self.mul*m%MOD
self.add = self.add*m%MOD
def getIndex(self, idx):
"""
:type idx: int
:rtype: int
"""
if idx>=len(self.vals):
return -1
return (self.vals[idx]*self.mul+self.add)%MOD