LeetCode 每日一题 2022/3/28-2022/4/3

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值