LeetCode 每日一题 2023/4/3-2023/4/9

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




4/3 1053. 交换一次的先前排列

从后往前
记录每个数字右侧第一次出现的位置
对于当前位置i num=arr[i]
遍历比num小的数值 是否在右侧出现过
挑选最大值且最靠前的位置

def prevPermOpt1( arr):
    """
    :type arr: List[int]
    :rtype: List[int]
    """
    n = len(arr)
    m = {}
    for i in range(n-1,-1,-1):
        num = arr[i]
        m[num] = i
        tmp = n
        for j in range(num-1,-1,-1):
            if j in m:
                tmp = m[j]
                break
        if tmp<n:
            arr[i],arr[tmp]=arr[tmp],arr[i]
            break
    return arr



4/4 1000. 合并石头的最低成本

每次减少k-1堆 最后剩下一对
所以n=len(stones) n%(k-1)=1
dp[l][r][t]描述在[l,r]区间内合并为t堆的最低成本
对于所有dp[i][i][1]=0 其他为正无穷
t=1时 dp[l][r][t] = d[l][r][k]+sum([l,r])
否则 dp[l][r][t] = min(dp[l][p][1]+d[p+1][r][t-1])
目标为dp[0][n-1][1]

def mergeStones(stones, k):
    """
    :type stones: List[int]
    :type k: int
    :rtype: int
    """
    n = len(stones)
    if n%(k-1)!=1 and k>2:
        return -1
    dp = [[[float("inf")]*(k+1) for _ in range(n)] for _ in range(n)]
    su = [0]*n
    s = 0
    for i in range(n):
        dp[i][i][1] = 0
        s += stones[i]
        su[i] = s
    for num in range(2,n+1):
        for l in range(n-num+1):
            r = l+num-1
            for t in range(2,k+1):
                for p in range(l,r,k-1):
                    dp[l][r][t] = min(dp[l][r][t],dp[l][p][1]+dp[p+1][r][t-1])
            tmp = su[r]
            if l>0:
                tmp -= su[l-1]
            dp[l][r][1] = min(dp[l][r][1],dp[l][r][k]+tmp)
    return dp[0][n-1][1]



4/5 2427. 公因子的数目

遍历每个数

def commonFactors(a, b):
    """
    :type a: int
    :type b: int
    :rtype: int
    """
    v = min(a,b)
    ans = 0
    for i in range(1,v+1):
        if a%i ==0 and b%i==0:
            ans +=1
    return ans



4/6 1017. 负二进制转换

先转换为正常二进制
对于奇数位 0,2,4,8 不会产生影响
对于偶数位 1,3,5 需要负二进制增加后一位相加实现
例如 2^3=8 需要(-2)4+(-2)3=16-8=8

def baseNeg2(n):
    """
    :type n: int
    :rtype: str
    """
    if n==0:
        return "0"
    l = [0]*40
    tmp = n
    cur = 0
    while tmp>0:
        l[cur]=tmp%2
        tmp//=2
        cur+=1
    cur = 0
    while cur<35:
        l[cur+1]+=l[cur]//2
        l[cur] = l[cur]%2
        if cur%2==0:
            cur +=1
            continue
        if l[cur]==1:
            l[cur+1]+=1
        cur+=1
    for i in range(29,-1,-1):
        if l[i]==1:
            cur = i
            break
    return "".join([str(l[loc]) for loc in range(cur,-1,-1)])

4/7 1040. 移动石子直到连续 II

按位置从小到大排序
假设有n个石子
最小移动次数 判断每个石子为滑动窗口左端 在连续n的长度下拥有最多的石子数m n-m及最小移动次数
最大移动次数 端点石子只移动到最近可移动的位置 那么处于0~n-2 或者1~n-1位置间的空位都能移动到

def numMovesStonesII(stones):
    """
    :type stones: List[int]
    :rtype: List[int]
    """
    n= len(stones)
    stones.sort()
    if stones[n-1]-stones[0]+1==n:
        return [0,0]
    mi = n
    r = 0
    for l in range(n):
        while r+1<n and stones[r+1]-stones[l]+1<=n:
            r+=1
        if r-l+1==n-1 and stones[r]-stones[l]+1==n-1:
            mi = min(mi,2)
        else:
            mi = min(mi,n-(r-l+1))
    ma = max(stones[n-2]-stones[0]+1,stones[n-1]-stones[1]+1)-(n-1)
    return [mi,ma]




4/8 1125. 最小的必要团队

技能最多16个 使用一个16位二进制表示技能拥有状态
遍历所有人 求出每个人的技能状态
dp[i] 表示满足技能i的最小人数 初始值为m
preskill[i] 表示最小dp[i]是由此技能而来
prepeo[i] 表示最小dp[i]是增加了这个人
从而记录每一步的人
最后从满状态开始往回寻找路径上的人

n = len(req_skills)
    m = len(people)
    skillind = {s:i for i,s in enumerate(req_skills)}
    dp = [m]*(1<<n)
    dp[0] = 0
    preskill = [0]*(1<<n)
    prepeo = [0]*(1<<n)
    for i,p in enumerate(people):
        curskill = 0
        for s in p:
            curskill |= 1<<skillind[s]
        for pre in range(1<<n):
            nxt = pre|curskill
            if dp[nxt]>dp[pre]+1:
                dp[nxt] = dp[pre]+1
                preskill[nxt] = pre
                prepeo[nxt] = i
    ans = []
    i = (1<<n)-1
    while i>0:
        ans.append(prepeo[i])
        i = preskill[i]
    return ans



4/9 2399. 检查相同字母间的距离

从头遍历 遇到第二次时判断两字母之间的距离

def checkDistances(s, distance):
    """
    :type s: str
    :type distance: List[int]
    :rtype: bool
    """
    m={}
    for i,c in enumerate(s):
        if c in m:
            dis = i-m[c]-1
            loc = ord(c)-ord("a")
            if distance[loc]!=dis:
                return False
            else:
                distance[loc] = 0
        else:
            m[c]=i
    return True



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值