[LeetCode316周赛] 贪贪贪

本文介绍了两道LeetCode周赛中的编程题目,分别是求解数组中最大公因数等于给定值的子数组数量和找到使数组元素相等的最小开销。第一题通过枚举和最大公约数计算得出答案,第二题利用中位数策略减少操作次数。解题策略涉及到数组处理、数学运算和最优化问题。
摘要由CSDN通过智能技术生成

[LeetCode316周赛]

6224. 最大公因数等于 K 的子数组数目

https://leetcode.cn/contest/weekly-contest-316/problems/number-of-subarrays-with-gcd-equal-to-k/

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 nums 的子数组中元素的最大公因数等于 k 的子数组数目。

子数组 是数组中一个连续的非空序列。

数组的最大公因数 是能整除数组中所有元素的最大整数。

输入:nums = [9,3,1,2,6,3], k = 3
输出:4
解释:nums 的子数组中,以 3 作为最大公因数的子数组如下(加粗字体):

  • [9,3,1,2,6,3]
  • [9,3,1,2,6,3]
  • [9,3,1,2,6,3]
  • [9,3,1,2,6,3]

Solution

枚举:

  • 每次循环找以当前元素为起始且满足条件的子数组数量

注意一个点:0 和任何数 x 的最大公约数都是 x

class Solution {
    public int gcd(int M, int N) {
        int rem;
        while (N > 0) {
            rem = M % N;
            M = N;
            N = rem;
        }
        return M;

    }
    public int subarrayGCD(int[] nums, int k) {
        int n = nums.length;
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] % k != 0) {
                continue;
            }
            int g = 0;
            for (int j = i; j < n; j++) {
                g = gcd(g, nums[j]);
                if (g == k) {
                    ans++;
                }
            }
        }
        return ans;
    }
}

6216. 使数组相等的最小开销

https://leetcode.cn/contest/weekly-contest-316/problems/minimum-cost-to-make-array-equal/

给你两个下标从 0 开始的数组 numscost ,分别包含 n 个 正 整数。

你可以执行下面操作 任意 次:

nums 中 任意 元素增加或者减小 1 。
对第 i 个元素执行一次操作的开销是 cost[i]

请你返回使 nums 中所有元素 相等 的 最少 总开销。

输入:nums = [1,3,5,2], cost = [2,3,1,14]
输出:8
解释:我们可以执行以下操作使所有元素变为 2 :

  • 增加第 0 个元素 1 次,开销为 2 。
  • 减小第 1 个元素 1 次,开销为 3 。
  • 减小第 2 个元素 3 次,开销为 1 + 1 + 1 = 3 。

总开销为 2 + 3 + 3 = 8 。
这是最小开销。

输入:nums = [2,2,2,2,2], cost = [4,2,8,1,3]
输出:0
解释:数组中所有元素已经全部相等,不需要执行额外的操作。

引例 462. 最小操作次数使数组元素相等 II

https://leetcode.cn/problems/minimum-moves-to-equal-array-elements-ii/

给你一个长度为 n 的整数数组 nums,返回使所有数组元素相等需要的最小操作数。

在一次操作中,你可以使数组中的一个元素加 1 或者减 1 。

输入:nums = [1,2,3]
输出:2
解释:
只需要两次操作(每次操作指南使一个元素加 1 或减 1):
[1,2,3] => [2,2,3] => [2,2,2]

解题思路

抽象化为一个递增数列,选择一个数,使得所有数与该数的差的和最小。
==> 中位数!!!

没错,我们的目标值就是 中位数

class Solution {
    public int minMoves2(int[] nums) {
        Arrays.sort(nums);
        int mid = nums[nums.length / 2];
        int ans = 0;
        for (int x : nums) {
            ans += Math.abs(x - mid);
        }
        return ans;
    }
}

Solution

该题和引例中的题类似,参考灵神的解法,只需要把 cost[i] 看作 nums[i] 出现的次数进行排列,然后按照上面的思路写就可以了。

引用灵神的代码,我自己写的 Java 版越界了:

class Solution:
    def minCost(self, nums: List[int], cost: List[int]) -> int:
        a = sorted(zip(nums, cost))
        s, mid = 0, sum(cost) // 2
        for x, c in a:
            s += c
            if s > mid:  # 把所有数变成 x
                return sum(abs(y - x) * c for y, c in a)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哇咔咔负负得正

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值