LeetCode 每日一题 2023/3/13-2023/3/19

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


目录

      • 3/13 2383. 赢得比赛需要的最少训练时长
      • 3/14 1605. 给定行和列的和求可行矩阵
      • 3/15 1615. 最大网络秩
      • 3/16 2488. 统计中位数为 K 的子数组
      • 3/17 2389. 和有限的最长子序列
      • 3/18 1616. 分割两个字符串得到回文串
      • 3/19 1625. 执行操作后字典序最小的字符串


3/13 2383. 赢得比赛需要的最少训练时长

一次遍历 如果无法击败则增加训练时间

def minNumberOfHours(initialEnergy, initialExperience, energy, experience):
    """
    :type initialEnergy: int
    :type initialExperience: int
    :type energy: List[int]
    :type experience: List[int]
    :rtype: int
    """
    ans = 0
    curen,curex = initialEnergy,initialExperience
    for i in range(len(energy)):
        print(i,ans,curen,curex)
        if curex<=experience[i]:
            ans += experience[i]+1-curex
            curex = experience[i]+1
        curex += experience[i]
        curen -= energy[i]
        if curen<=0:
            ans =ans - curen+1
            curen=1
    return ans



3/14 1605. 给定行和列的和求可行矩阵

既然必定存在一个答案 各行和总数=各列和总数
目的是找到分配数值的方案
根据n,m = len(rowSum),len(colSum)
我们可以知道答案是一个n*m的矩阵
1.可以先将列之和分配到第一行的各列之中
例:rowSum = [5,7,10], colSum = [8,6,8]
8,6,8
0,0,0
0,0,0

此后数值的增减操作只在同一列中进行
所以每列之和已经满足条件不需要再考虑
2.依次根据rowSum 通过减去数值来使该行和满足条件
减去的数值增加到该列中的下一行中(列之和不变)
处理第一行
5,0,0
3,6,8
0,0,0

处理第二行
5,0,0
3,4,0
0,2,8

此时第三行自动满足条件

def restoreMatrix(rowSum, colSum):
    """
    :type rowSum: List[int]
    :type colSum: List[int]
    :rtype: List[List[int]]
    """
    n,m = len(rowSum),len(colSum)
    ans = [[0]*m for _ in range(n)]
    ans[0] = colSum[:]
    for i in range(n-1):
        target = rowSum[i]
        for j in range(m):
            if target>=ans[i][j]:
                target-=ans[i][j]
            else:
                tmp = ans[i][j]
                ans[i][j] = target
                ans[i+1][j] = tmp-target
                target = 0
    return ans



3/15 1615. 最大网络秩

遍历所有路 记录每个节点拥有的道路 以及其连接的其他节点
选取两两节点 计算其拥有的秩

def maximalNetworkRank(n, roads):
    """
    :type n: int
    :type roads: List[List[int]]
    :rtype: int
    """
    from collections import defaultdict
    way = defaultdict(int)
    nxt = defaultdict(set)
    for i,j in roads:
        way[i]+=1
        way[j]+=1
        nxt[i].add(j)
        nxt[j].add(i)
    ans = 0
    for i in range(n-1):
        for j in range(i+1,n):
            tmp = way[i]+way[j]
            if j in nxt[i]:
                tmp-=1
            ans = max(ans,tmp)
    return ans



3/16 2488. 统计中位数为 K 的子数组

根据题意k是必须选择的
找到k的位置
该位置标签设定为0
分别向左右判断标签 比k大的+1 比k小的-1
记录左右各个位置标签状态
从左右分别选取一个位置标签 使其相加等于0或1 可以满足条件

def countSubarrays(nums, k):
    """
    :type nums: List[int]
    :type k: int
    :rtype: int
    """
    from collections import defaultdict
    n = len(nums)
    ind = 0
    left,right=defaultdict(int),defaultdict(int)
    for i in range(n):
        if nums[i]==k:
            ind=i
            break
    cur = 0
    for i in range(ind+1,n):
        if nums[i]<k:
            cur-=1
        else:
            cur+=1
        right[cur]+=1
    cur = 0
    for i in range(ind-1,-1,-1):
        if nums[i]<k:
            cur-=1
        else:
            cur+=1
        left[cur]+=1
        
    ans = 1+left[0]+right[0]+left[1]+right[1]
    
    if len(left)<len(right):
        for k,v in left.items():
            ans += v*right[0-k]
            ans += v*right[1-k]
    else:
        for k,v in right.items():
            ans += v*left[0-k]
            ans += v*left[1-k]
    return ans



3/17 2389. 和有限的最长子序列

排序后 前缀和
从前缀和序列中寻找

def answerQueries(nums, queries):
    """
    :type nums: List[int]
    :type queries: List[int]
    :rtype: List[int]
    """
    from itertools import accumulate
    import bisect
    nums.sort()
    s = list(accumulate(nums))
    return [bisect.bisect_right(s, q) for q in queries]



3/18 1616. 分割两个字符串得到回文串

长度为n
双指针i,j 一个从a头部开始 一个从b尾部开始
两指针同时向中间移动 直到i,j交叉i>=j 或者遇到不同字符

def checkPalindromeFormation(a, b):
    """
    :type a: str
    :type b: str
    :rtype: bool
    """
    n = len(a)
    def check(a,b):
        i,j=0,n-1
        while i<j and a[i]==b[j]:
            i +=1
            j -=1
        return i>=j or a[i:j+1]==a[i:j+1][::-1] or b[i:j+1]==b[i:j+1][::-1]
    return check(a,b) or check(b,a)



3/19 1625. 执行操作后字典序最小的字符串

广搜 遍历所有可能

def findLexSmallestString(s, a, b):
    """
    :type s: str
    :type a: int
    :type b: int
    :rtype: str
    """
    l = [s]
    mem = {s}
    ans = s
    while l:
        tmp = []
        for v in l:
            if ans>v:
                ans = v
            s1 = v[-b:]+v[:-b]
            s2 = ''.join([str((int(c)+a)%10) if i&1 else c for i,c in enumerate(v)])
            for t in (s1,s2):
                if t not in mem:
                    mem.add(t)
                    tmp.append(t)
        l = tmp[:]
    return ans



你可能感兴趣的:(Exercise,leetcode,算法,职场和发展)