[LeetCode周赛复盘] 第 376 场周赛20231217

[LeetCode周赛复盘] 第 376 场周赛20231217

    • 一、本周周赛总结
    • 100149. 找出缺失和重复的数字![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/347f99d7222f4b8a9c9b14fdff240e4d.png)
      • 2. 思路分析
      • 3. 代码实现
    • 100161. 划分数组并满足最大差限制
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 100151. 使数组成为等数数组的最小代价
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 100123. 执行操作使频率分数最大
      • 2. 思路分析
      • 3. 代码实现
    • 参考链接

一、本周周赛总结

  • 原题我调了半天,太傻了。。
  • T1 模拟。
  • T2 捞币翻译,排序贪心模拟。
  • T3 中位数定理+模拟/二分。
  • T4 中位数定理+滑窗。

100149. 找出缺失和重复的数字[LeetCode周赛复盘] 第 376 场周赛20231217_第1张图片

2. 思路分析

按题意模拟即可。

3. 代码实现

class Solution:
    def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]:
        n = len(grid)
        b = set(range(1,n*n+1))
        cnt = Counter()
        for row in grid:
            for v in row:
                b.discard(v)
                cnt[v]+=1
                if cnt[v] == 2:
                    a = v
        return [a, b.pop()]

100161. 划分数组并满足最大差限制

100161. 划分数组并满足最大差限制

1. 题目描述

[LeetCode周赛复盘] 第 376 场周赛20231217_第2张图片

2. 思路分析

翻译害人不浅,根本就不是子数组,原文是Divide the array into one or more arrays of size 3 satisfying the following conditions:

  • 其实是分组,不要求连续,类似与子序列但可以重排。
  • 那么排序贪心模拟即可,相邻的三个必须同组。

3. 代码实现

class Solution:
    def divideArray(self, nums: List[int], k: int) -> List[List[int]]:
        nums.sort()
        ret = []
        for i in range(0, len(nums), 3):
            if nums[i + 2] - nums[i] > k:
                return []
            ret.append(nums[i:i + 3])
        return ret

100151. 使数组成为等数数组的最小代价

100151. 使数组成为等数数组的最小代价

1. 题目描述

[LeetCode周赛复盘] 第 376 场周赛20231217_第3张图片

2. 思路分析

  • 中位数定理。要让数组里的数都变成同一个数,总距离最小,那么就是变成中位数。
  • 显然可以找到离中位数最近的那个回文数即可。
  • 题目限制<1e9才是中位数,因此我们可以枚举中位数的一半,打表预处理所有中位数。然后在这个表里二分。

  • 另外,由于两个回文数间距最大只有1e4级别,其实可以直接从中位数开始暴力向两边扩展。

3. 代码实现

biao=list(range(1,10))
for i in range(10**4):
    s = str(i)
    p = int(s + s[::-1])
    if p < 10**9:
        biao.append(p)
    for j in range(10):
        p = int(s +str(j)+ s[::-1])
        if p < 10**9:
            biao.append(p)
biao = sorted(set(biao))

class Solution:
    def minimumCost(self, nums: List[int]) -> int:
        n = len(nums)
        nums.sort()
        
        pre = [0] + list(accumulate(nums))
        def f(x):
            p = bisect_left(nums,x)
            s = 0
            if p > 0:
                s += x*p - pre[p-1+1] + pre[0] 
            if p < n:
                s += pre[n] - pre[p] - x*(n-p)
            return s 
        ans = inf
        p = bisect_left(biao,nums[(n-1)//2])
        if p:
            ans = f(biao[p-1])
        if p < len(biao):
            ans = min(ans,f(biao[p]))
        return ans        
class Solution {
    public int[][] divideArray(int[] nums, int k) {
        Arrays.sort(nums);
        List<int[]> ret = new ArrayList<>();

        for (int i = 0; i < nums.length; i += 3) {
            if (i + 2 < nums.length && nums[i + 2] - nums[i] > k) {
                return new int[][]{}; 
            }

            int[] subArray = Arrays.copyOfRange(nums, i, Math.min(i + 3, nums.length));
            ret.add(subArray);
        }

        return ret.toArray(new int[0][]);
    }
}

100123. 执行操作使频率分数最大

[100123. 执行操作使频率分数最大[LeetCode周赛复盘] 第 376 场周赛20231217_第4张图片

2. 思路分析

  • 我可真菜啊,华子原题调这半天。
  • 应用中位数定理+滑窗。
  • 枚举右端点,左端点向左不合法的情况下,下一个右端点也必不合法,左端点可以右移。

3. 代码实现

class Solution:
    def maxFrequencyScore(self, nums: List[int], k: int) -> int:
        if k == 0:
            return max(Counter(nums).values())
        nums.sort()
        pre = [0] + list(accumulate(nums))
        n = len(nums)
        def f(l,r):
            mid = (l+r)//2
            p = nums[mid]*(mid-l+1) - (pre[mid+1] - pre[l])   + pre[r+1] - pre[mid] - nums[mid] * (r-mid+1)            
            return p <= k
        l = ans = 0
        for r in range(n):
            while not f(l,r):
                
                l += 1
            ans = max(ans, r - l + 1)
        return ans    

参考链接

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