LeetCode 每日一题 2022/2/28-2022/3/6

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




2/28 1601. 最多可达成的换楼请求数目

因为requests最多只有16个
我们可以枚举所有请求情况
使用一个16位的二进制数代表取了若干个请求的情况 1代表实现请求
对每一种请求模拟后 如果满足情况 那么更新请求最大个数

def maximumRequests(n, requests):
    """
    :type n: int
    :type requests: List[List[int]]
    :rtype: int
    """
    ans = 0
    m = len(requests)
    def onenum(num):
        one = 0
        while num:
            num&=(num-1)
            one+=1
        return one
        
    for mask in range(1<<m):
        num = onenum(mask)
        if num<ans:
            continue
        l = [0]*n
        for i,(x,y) in enumerate(requests):
            if mask&(1<<i):
                l[x]-=1
                l[y]+=1
        tag = True
        for i in range(n):
            if l[i]!=0:
                tag = False
                break
        if tag:
            ans = num
    return ans

3/1 6. Z 字形变换

位置0开始计算
第j行 第一个数是j 间隔有两种类型 step1=2*(n-j-1) step2 = 2*j

def convert(s, numRows):
    """
    :type s: str
    :type numRows: int
    :rtype: str
    """
    if numRows==1:
        return s
    ans = ""
    num = len(s)
    for j in range(numRows):
        step1 = 2*(numRows-j-1)
        step2 = 2*j
        if step1==0 or step2==0:
            step1,step2=max(step1,step2),max(step1,step2)
        steps = [step1,step2]
        loc = j
        v = 0
        while loc<num:
            ans += s[loc]
            loc +=steps[v%2]
            v+=1
    return ans

3/2 564. 寻找最近的回文数

如果位数变动 多一位最接近的肯定是100…001 少一位肯定是99…99
两种情况可以特殊考虑
如果位数不变动 为了使差值最小 肯定变动后半部分
前半部分保持不变 num=len(n) 前半部分为x=(num+1)//2位
考虑 x-1,x,x+1 三种情况即可

def nearestPalindromic(n):
    """
    :type n: str
    :rtype: str
    """
    num = len(n)
    more = 10**num+1
    less = 10**(num-1)-1
    ans = ""
    
    if len(n)==1:
        return str(int(n)-1)
    
    ori = int(n)
    diff = min(more-ori,ori-less)
    if more-ori<ori-less:
        ans = str(more)
    else:
        ans = str(less)
 
    half = int(n[:(num+1)//2])
    for x in range(half-1,half+2):
        if num%2==0:
            y = x
        else:
            y = x//10
        while y:
            x = x*10+y%10
            y//=10
        if x==ori:
            continue
        print(x,abs(x-ori),diff,ans)
        if abs(x-ori)<diff or(abs(x-ori)==diff and len(ans)>len(str(x))):
            diff = abs(x-ori)
            ans = str(x)
    
    return ans

3/3 258. 各位相加

模拟 取各位和

def addDigits(num):
    """
    :type num: int
    :rtype: int
    """
    while num>9:
        tmp = num
        num = 0
        while tmp>0:
            num += tmp%10
            tmp = tmp//10
    return num

3/4 2104. 子数组范围和

1.暴力 遍历所有子数组
2.单调栈
作为最大值的贡献:
维护一个单调递减的栈 x,y (nums[x]>nums[y])
如果此时z位置的值大于y 需要处理y
y作为最大值的子数组个数(y-x)*(z-y)
贡献为nums[y]*个数
作为最小值的贡献 类似 只是贡献为负

def subArrayRanges(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    n = len(nums)
    ans = 0
    for i in range(n-1):
        maxv,minv = nums[i],nums[i]
        for j in range(i+1,n):
            maxv = max(maxv,nums[j])
            minv = min(minv,nums[j])
            ans += maxv-minv
    return ans

def subArrayRanges2(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    ans=0
    stack = []
    for i,num in enumerate(nums+[float('inf')]):
        while stack and nums[stack[-1]]<num:
            j = stack.pop()
            left = stack[-1] if stack else -1
            ans += nums[j]*(i-j)*(j-left)
        stack.append(i)
    stack = []
    for i,num in enumerate(nums+[float('-inf')]):
        while stack and nums[stack[-1]]>num:
            j = stack.pop()
            left = stack[-1] if stack else -1
            ans -= nums[j]*(i-j)*(j-left)
        stack.append(i)
    return ans

3/5 521. 最长特殊序列 Ⅰ

如果两个字符串相等 则不存在
否则最长的字符串子序列取自身 必定不是另一个的子序列

def findLUSlength( a, b):
    """
    :type a: str
    :type b: str
    :rtype: int
    """
    if a==b:
        return -1
    return max(len(a),len(b))

3/6 2100. 适合打劫银行的日子

前time天非递增 后time天非递减
两个条件分开来考虑
qian[i]用来记录从前往后到位置i最长非递增长度
hou[i]用来记录从i往后最长非递减长度

def goodDaysToRobBank(security, time):
    """
    :type security: List[int]
    :type time: int
    :rtype: List[int]
    """
    n = len(security)
    qian,hou = [0]*n,[0]*n
    for i in range(1,n):
        if security[i]<=security[i-1]:
            qian[i] = qian[i-1]+1
        if security[n-i-1]<=security[n-i]:
            hou[n-i-1]=hou[n-i]+1
    ans = []
    for i in range(time,n-time):
        if qian[i]>=time and hou[i]>=time:
            ans.append(i)
    return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值