[LeetCode周赛复盘] 第 354 场周赛20230716

[LeetCode周赛复盘] 第 354 场周赛20230716

    • 一、本周周赛总结
    • 6889. 特殊元素平方和
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 6929. 数组的最大美丽值
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 6927. 合法分割的最小下标
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 6924. 最长合法子字符串的长度
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 参考链接

一、本周周赛总结

  • T1 模拟。
  • T2 RUPQ 差分/树状数组。
  • T3 前后缀分解。
  • T4 双指针+trie(py负优化)。
    [LeetCode周赛复盘] 第 354 场周赛20230716_第1张图片

6889. 特殊元素平方和

6889. 特殊元素平方和

1. 题目描述

[LeetCode周赛复盘] 第 354 场周赛20230716_第2张图片

2. 思路分析

按题意模拟即可。

3. 代码实现

class Solution:
    def sumOfSquares(self, nums: List[int]) -> int:
        return sum(v*v for i,v in enumerate(nums,start=1) if len(nums)%i==0)

6929. 数组的最大美丽值

6929. 数组的最大美丽值

1. 题目描述

[LeetCode周赛复盘] 第 354 场周赛20230716_第3张图片

2. 思路分析

  • 注意到值域很小,因此可以值域当下标,记录每个下标可以被访问多少次。
  • 那么其实是个区间+1。用差分可以搞。树状数组也可以。
  • 实现时,只需要对值域mn~mx处理即可,因为所有数都加相同的k,边界以外的次数一定不会超过边界(它们一定会路过边界)。

3. 代码实现

class Solution:
    def maximumBeauty(self, nums: List[int], k: int) -> int:
        mx = max(nums)
        d = [0]*(mx+2)
        for v in nums:
            x,y = max(0,v-k), min(mx,v+k)
            d[x] += 1
            d[y+1] -= 1 
            
        return max(accumulate(d))

6927. 合法分割的最小下标

6927. 合法分割的最小下标

1. 题目描述

[LeetCode周赛复盘] 第 354 场周赛20230716_第4张图片

2. 思路分析

  • 前后缀分解。
  • 先计算出主元素x和它出现的次数y。那么前后缀的相同主元素只能是x。
  • 那么可以从头向后遍历,记录x的出现次数p,并计算后边剩余的次数y-p。
  • 找到第一个满足条件的下标即可。

3. 代码实现

class Solution:
    def minimumIndex(self, nums: List[int]) -> int:
        n = len(nums)
        cnt = Counter(nums)
        x,y = cnt.most_common(1)[0]
        p = 0
        for i,v in enumerate(nums):
            if v == x:
                p += 1 
                if p*2 > i+1 and (y-p)*2>(n-i-1):
                    return i
        return -1

6924. 最长合法子字符串的长度

6924. 最长合法子字符串的长度

1. 题目描述

[LeetCode周赛复盘] 第 354 场周赛20230716_第5张图片

2. 思路分析

  • 最长子段首先想到双指针/滑窗。
  • 枚举每个字母作为子段的右端点。尝试检查这个尾缀里是否再forbid里。
  • 由于forbid长度最多10,因此只需要暴力检查10次尾缀,找到最短那个fb尾缀,把左窗口挪过来,注意是l=j+1,因为要破坏这个非法单词。
  • 这样复杂度是n1010,每个字符要检查10次,每次检查复杂度是len(s)=10。

  • 可以用字典树trie优化成n*10。但是实测py果然还是切片+朴素set更快。
  • 对forbid逆序建树。
  • 枚举c为右端点时,也逆序向前组成字符串,然后去trie里判断是否存在这个单词。
  • 由于检查也是从右向左,同步检查,因此复杂度就是10。

3. 代码实现

朴素set

class Solution:
    def longestValidSubstring(self, word: str, forbidden: List[str]) -> int:
        fb = set(forbidden)
        l = ans = 0 
        for r,c in enumerate(word):            
            for j in range(r,max(l-1,r-10),-1):
                if word[j:r+1] in fb:
                    l = j+1
                    break
            # print(r,l)
            ans = max(ans, r-l+1)
        return ans                       

trie

class Solution:
    def longestValidSubstring(self, word: str, forbidden: List[str]) -> int:
        trie = {}
        for s in  forbidden:
            s = s[::-1]
            cur = trie 
            for c in s:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur['#'] = 1
        def query(s):
            cur = trie
            for i,c in enumerate(s,start=1):
                if c not in cur:
                    return 0 
                cur = cur[c]
                if '#' in cur:
                    return i 
            return 0
        l = ans = 0 
        for r,c in enumerate(word):     
            s = word[max(l,r-9):r+1] 
            i = query(s[::-1])
            if i:
                l = r - i+2
            ans = max(ans, r-l+1)
        return ans                 

参考链接

你可能感兴趣的:(力扣周赛复盘,leetcode,算法,职场和发展)