这是 LeetCode 2344 题的 C++ 实现版本。这道题的核心思路与 Java 版本完全一致,都是利用最大公约数(GCD)结合排序贪心来解决。

💡 核心思路解析

1. 求最大公约数:首先遍历 numsDivide 数组,求出所有元素的最大公约数 g。
2. 排序与贪心:将 nums 数组从小到大排序。为了让删除次数最少,我们需要找到 nums 中最小的、能够整除 g 的元素。
3. 计算删除次数:遍历排序后的 nums,找到第一个能整除 g 的元素(即 g % nums[i] == 0),它的下标 i 就是需要删除的最少次数。如果遍历完都没有找到,说明无法满足条件,返回 -1。

💻 C++ 代码实现

include 
include  // 引入 sort 排序算法
include    // 引入 std::gcd (C++17 标准库自带)

using namespace std;

class Solution {
public:
    int minOperations(vector& nums, vector& numsDivide) {
        // 1. 求出 numsDivide 所有元素的最大公约数 (GCD)
        // C++17 及以上版本可以直接使用 std::gcd,需要包含  头文件
        int g = numsDivide[0];
        for (int num : numsDivide) {
            g = gcd(g, num);
        }

        // 2. 将 nums 从小到大排序,以便找到最小的满足条件的数
        sort(nums.begin(), nums.end());

        // 3. 遍历 nums,找到第一个能整除最大公约数 g 的元素
        for (int i = 0; i < nums.size(); i++) {
            // 如果 g 能被 nums[i] 整除,说明 nums[i] 能整除 numsDivide 中的所有元素
            if (g % nums[i] == 0) {
                return i; // 下标 i 即为需要删除的最少次数
            }
        }

        // 4. 如果没有找到满足条件的数,返回 -1
        return -1;
    }

    // 如果使用的编译器不支持 C++17 标准,可以手动实现辗转相除法求最大公约数
    /*
    int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    */
};

📊 复杂度分析
* 时间复杂度:O(n log n + m)。其中 n 是 nums 的长度,m 是 numsDivide 的长度。求最大公约数需要遍历 numsDivide(O(m)),排序 nums 需要 O(n log n),最后遍历 nums 需要 O(n)。
* 空间复杂度:O(1)(不考虑排序算法本身占用的栈空间,仅使用了常数级别的额外变量)。

在 C++ 中,使用 std::sort 和 std::gcd 可以非常简洁高效地解决这道问题。如果你使用的是较老版本的 C++ 编译器(低于 C++17),可以直接启用代码注释中的自定义 gcd 函数即可。

 

更多推荐