LeetCode 每日一题 2024/6/24-2024/6/30

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




6/24 503. 下一个更大元素 II

循环数组 拼接两个数组即可
单调栈保存下标 遇到栈顶小于当前值
则栈顶下标结果为当前值

def nextGreaterElements(nums):
    """
    :type nums: List[int]
    :rtype: List[int]
    """
    n=len(nums)
    ans=[-1]*n
    st = []
    
    for i in range(2*n-1):
        while st and nums[st[-1]]<nums[i%n]:
            ans[st.pop()]=nums[i%n]
        st.append(i%n)
    return ans



6/25 2732. 找到矩阵中的好子集

将每一行看做一个二进制数
如果答案至少有一行 那么这一行都为0
如果答案至少两行 那么每一列最多一个1 这两行二进制and为0
如果答案至少3行 每一列最多为1 和两行相同
如果答案至少4行 每一列和不超过2
因为两行找不到答案说明任选两行至少存在一列这两行都为1 但其他两行必须为0
若要满足这个条件至少需要4列 但题目矩阵列数n<=5 所以不存在
只考虑答案为1行或2行的情况即可

def goodSubsetofBinaryMatrix(grid):
    """
    :type grid: List[List[int]]
    :rtype: List[int]
    """
    m = {}
    for i,row in enumerate(grid):
        mask = 0
        for j,v in enumerate(row):
            mask |= v<<j
        if mask ==0:
            return [i]
        m[mask]=i
    
    for x,i in m.items():
        for y,j in m.items():
            if (x&y)==0:
                return sorted([i,j])
    return []



6/26 2741. 特别的排列

长度<14 用一个最长14位的二进制数s 描述当前可以用的数值位置
dfs(s,i) 搜索当前集合s的情况下 选取i位置的数值放在当前位置的情况

def specialPerm(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    MOD=10**9+7
    mem={}
    def dfs(s,i):
        if (s,i) in mem:
            return mem[(s,i)]
        if s==0:
            return 1
        res = 0
        pre = nums[i]
        for j,x in enumerate(nums):
            if s>>j &1 and(pre%x==0 or x%pre==0):
                res = (res+dfs(s^(1<<j),j))%MOD
        mem[(s,i)]=res
        return res
        
        
    n = len(nums)
    ans = 0
    u = (1<<n)-1
    for i in  range(n):
        ans = (ans+dfs(u^(1<<i),i))%MOD
    return ans



6/27 2734. 执行子串操作后的字典序最小字符串

除了a 别的字符执行都会变小 所以从左到右遇到第一个非a字符开始执行操作
遇到a停止操作
如果全是a 则将最后一个操作一次为 z

def smallestString(s):
    """
    :type s: str
    :rtype: str
    """
    l=list(s)
    for i,c in enumerate(l):
        if c=='a':
            continue
        for j in range(i,len(l)):
            if l[j]=='a':
                break
            l[j]=chr(ord(l[j])-1)
        return ''.join(l)
    l[-1]='z'
    return ''.join(l)



6/28 2742. 给墙壁刷油漆

dp[i,j]表示前i面墙 免费工作次数为j的最小开销
对于第i堵墙
如果付费将花费cost[i] 并且获得time[i]次免费油漆匠工作机会
如果免费 将减少1次免费工作机会
j最多可以为n 最小为-n
使用0~2n来代替
因为依次判断i 所以dp[i,j]只会影响dp[i+1,x]
所以只需要一维dp[j]即可

def paintWalls(cost, time):
    """
    :type cost: List[int]
    :type time: List[int]
    :rtype: int
    """
    n= len(cost)
    dp=[float('inf')]*(2*n+1)
    dp[n]=0
    for (c,t) in zip(cost,time):
        g=[float('inf')]*(2*n+1)
        for j in range(2*n+1):
            g[min(j+t,2*n)]=min(g[min(j+t,2*n)],dp[j]+c)
            if j>0:
                g[j-1]=min(g[j-1],dp[j])
        dp=g
    return min(dp[n:])



6/29 2710. 移除字符串中的尾随零

从后往前判断 如果遇到0则往前一步

def removeTrailingZeros(num):
    """
    :type num: str
    :rtype: str
    """
    for i in range(len(num)):
        if num[-1-i]!='0':
            break
    return num if i==0 else num[:-i]




6/30 494. 目标和

1.dp 动态规划
dp[i][value] 前i个数 答案为value的可能情况
因为-1000<=value<=1000
方便起见 全部加1000 => 0<=value<=2000
v为当前位置数值 j为当前考虑value值
dp[i][j] = dp[i-1][j-v] + dp[i-1][j+v]
2.dp 动态规划
总和为total 变负数的总和绝对值为neg 正数总和total-neg target=total-2*neg
转化为neg = (total-target)/2 选取若干个数 总和为neg
dp[i][j] 前i个数 总和可以为j的可能方式
num = nums[i]
dp[i+1][j] = dp[i][j]+dp[i][j-num]

def findTargetSumWays(nums, target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    total = sum(nums)
    if target>total or target<-total:
        return 0
    n = len(nums)
    m = 2001
    dp = [[0]*m for _ in range(n+1)]
    dp[0][nums[0]+1000]+=1
    dp[0][1000-nums[0]]+=1
    for i in range(1,n):
        v = nums[i]
        for j in range(m):
            if j-v>=0 and dp[i-1][j-v]>0:
                dp[i][j] += dp[i-1][j-v]
            if j+v<m and dp[i-1][j+v]>0:
                dp[i][j]+=dp[i-1][j+v]
    return dp[n-1][target+1000]
                
def findTargetSumWays2(nums, target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """            
    diff = sum(nums) - target
    if diff<0 or diff%2==1:
        return 0
    n = len(nums)
    neg = diff//2
    dp = [[0]*(neg+1) for _ in range(n+1)]
    dp[0][0]=1
    for i in range(n):
        num = nums[i]
        for j in range(neg+1):
            dp[i+1][j]=dp[i][j]
            if j>=num:
                dp[i+1][j] += dp[i][j-num]
    return dp[n][neg]



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值