记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
3/28 693. 交替位二进制数
1.最后一位与最后第二位比较是否不同
2.n如果满足01交替 则n与n移动以为后异或得到的结果m必定都为1
def hasAlternatingBits(n):
"""
:type n: int
:rtype: bool
"""
while n:
if (n&1)^((n>>1)&1)==1:
n = n>>1
else:
return False
return True
def hasAlternatingBits2(n):
"""
:type n: int
:rtype: bool
"""
m = n^(n>>1)
return m&(m+1)==0
3/29 2024. 考试的最大困扰度
滑动窗口
l,r为一个滑动窗口 r不停右移 m记录滑动窗口内T,F的个数
需要满足连续相同 滑动窗口内T,F的较小个数需要不大于k
如果不满足条件将l右移 减小滑动窗口
def maxConsecutiveAnswers(answerKey, k):
"""
:type answerKey: str
:type k: int
:rtype: int
"""
l,r = 0,0
m = {"T":0,"F":0}
ans = 0
while r<len(answerKey):
m[answerKey[r]]+=1
while min(m["T"],m["F"])>k:
m[answerKey[l]]-=1
l+=1
ans = max(ans,r-l+1)
r+=1
return ans
3/30 1606. 找到处理最多请求的服务器
avset存储当前可用的服务器
servnum存储每个服务器被使用的次数
endtime 最小堆 存储(结束时间,服务器编号)
maxnum记录单服务器被使用的最大次数
队列li 从小到大排列当前可用服务器
遍历请求 当前时间点为time 持续keep 服务器serv=loc%k
如果endtime不为空 将endtime中在当前时间点time前的服务器释放
将其加入avset,li
如果当前可用服务器avset为空 则当前请求舍弃
如果对应服务器serv不可用
则在li中找到大于serv的第一个服务器 如果不存在比serv大的服务器
则取li中编号最小的服务器为serv
将这个serv服务器从avset,li中取出
并且这个服务器将在time+keep点才能释放 在最小堆中加入(time+keep,serv)
这个服务器使用次数+1 更新最大使用次数
最后 找到所有使用了maxnum次数的服务器
def busiestServers(k, arrival, load):
"""
:type k: int
:type arrival: List[int]
:type load: List[int]
:rtype: List[int]
"""
from collections import defaultdict
import heapq
import bisect
avset = set([x for x in range(k)])
servnum = defaultdict(int)
endtime = []
heapq.heapify(endtime)
maxnum = 0
li = list(range(k))
for loc,time in enumerate(arrival):
keep = load[loc]
serv = loc%k
while endtime and endtime[0][0]<=time:
t = heapq.heappop(endtime)
avset.add(t[1])
bisect.insort(li,t[1])
if len(avset)==0:
continue
if serv not in avset:
loc = bisect.bisect_left(li,serv)
if loc==len(li):
loc = 0
serv = li[loc]
end = time+keep
li.remove(serv)
avset.remove(serv)
heapq.heappush(endtime,(end,serv))
servnum[serv]+=1
maxnum = max(servnum[serv],maxnum)
ans = []
for k in servnum.keys():
v = servnum[k]
if v==maxnum:
ans.append(k)
return(ans)
3/31 728. 自除数
判断范围内每一个数是否为自除数
def selfDividingNumbers(left, right):
"""
:type left: int
:type right: int
:rtype: List[int]
"""
def isDivid(num):
ori = num
while num:
v = num%10
if v==0 or ori%v>0:
return False
num = num//10
return True
ans = []
for i in range(left,right+1):
if isDivid(i):
ans.append(i)
return ans
4/1 954. 二倍数对数组
将正负数分开讨论 存储于pos,neg 负数取绝对值
分别从小到大排序
对于从小到大排序的正数序列arr
l存储需要的二倍数 l也是从小到大 loc表示当前已满足的二倍数位置
对于arr中的i
如果loc在队列尾端说明当前没有需要满足的二倍数
或者i小于当前最小的二倍数 将2*i放入队列中
如果i等于当前需要的最小二倍数 则将位置loc往后移动
如果i大于当前需要的最小二倍数 i是非递减的 所以这个最小二倍数永远无法取到 返回False
最后如果loc位于l尾端 说明所有二倍数都被找到 返回True
def canReorderDoubled(arr):
"""
:type arr: List[int]
:rtype: bool
"""
neg,pos = [],[]
for v in arr:
if v>=0:
pos.append(v)
else:
neg.append(-v)
if len(pos)%2==1:
return False
def check(arr):
l = []
loc = 0
for i in arr:
if len(l)==loc or i<l[loc]:
l.append(2*i)
elif i==l[loc]:
loc+=1
else:
return False
if len(l)>loc:
return False
return True
pos.sort()
neg.sort()
return check(pos) and check(neg)
4/2 420. 强密码检验器
首先判断密码中是否包含大小写和数字 如果没有的必须需要添加
如果长度小于6:
需要补齐到6 如果有连续3,4,5个字符 添加一个其他字符在中间即可 并且需要包含三类字符
如果长度在6~20间:
此时只要进行替换操作即可 对于k个相同字符 进行k//3次操作 并且满足包含三类字符
如果长度在20以上:
此时进行删除和替换操作 删除操作为num-20 替换操作为所有连续3次以上字符k//3的和
但是在进行删除操作时 有可能减少替换操作次数
如果k%3=0 删除1个字符 可以将替换操作减少1
如果k%3=1 删除2个字符 可以将替换操作减少1
如果k%3=2 删除3个字符 可以将替换操作减少1
之后每多删除3个字符 可以减少一次替换操作
可以统计所有替换操作次数 再根据删除操作次数 来减少替换操作
def strongPasswordChecker(password):
"""
:type password: str
:rtype: int
"""
num = len(password)
lower,upper,digit = 1,1,1
for c in password:
if c.islower():
lower = 0
elif c.isupper():
upper = 0
elif c.isdigit():
digit = 0
base = digit+upper+lower
if num<6:
return max(6-num,base)
elif num<=20:
keep = 0
cur = ""
ac = 0
for c in password:
if c==cur:
keep+=1
else:
ac += keep//3
keep = 1
cur = c
ac +=keep//3
return max(ac,base)
else:
replace,remove = 0,num-20
rm2 = 0
keep = 0
cur = ""
for c in password:
if c==cur:
keep+=1
else:
if remove>0 and keep>2:
if keep%3 ==0:
remove -=1
replace -=1
elif keep%3==1:
rm2 +=1
replace += keep//3
keep = 1
cur = c
if remove>0 and keep>2:
if keep%3 ==0:
remove -=1
replace -=1
elif keep%3==1:
rm2 +=1
replace += keep//3
#删除两个字符 减少一次替换
v2 = min(replace,rm2,remove//2)
replace -=v2
remove -=v2*2
#每次替换必定有三个连续相同字符
v3 = min(replace,remove//3)
replace -=v3
remove -= v3*3
return num-20 + max(replace,base)
4/3 744. 寻找比目标字母大的最小字母
字符列表经过排序 第一个字符为最小 记录第一个字符
从小到大依次判断是否大于target 如果第一次找到大于target的字符 为最小字母返回
如果一直到最后都没找到 说明要从头循环 第一个字符为最小
def nextGreatestLetter(letters, target):
"""
:type letters: List[str]
:type target: str
:rtype: str
"""
ans = letters[0]
for c in letters:
if c>target:
return c
return ans