首页 > 编程语言 >2654. 使数组所有元素变成 1 的最少操作次数(c++,gcd性质)

2654. 使数组所有元素变成 1 的最少操作次数(c++,gcd性质)

时间:2023-05-17 20:01:42浏览次数:53  
标签:cnt gcd nums int c++ 2654 ++ 数组

题目链接:2654. 使数组所有元素变成 1 的最少操作次数

方法一:计算最短的gcd为1的子数组

解题思路

  • 本题目标:使得所有的数组元素都变为 \(1\),通过求相邻元素 \(gcd\) 将其赋值给一方的方式;
  • 思路:
    • 若想操作数最少,那么就是不为 \(1\) 的数 \(x\) 和 1 求 \(gcd\),即 \(x = gcd(x, 1)\),这样一次就可以将 \(x\) 变为 \(1\);
    • 因此现在至于要找最短的 \(gcd\) 为 \(1\) 的子数组,先将其中一个数转换为 \(1\) ,然后将其他不等于 \(1\) 的元素通过一次操作变为 \(1\);
  • 特殊情况:
    • 数组整体的 \(gcd\) 不为 \(1\),说明不管怎么操作都不能出现 \(1\),那么一定不能变为 \(1\);
    • 数组中已经存在 \(1\),那么对于已经是 \(1\) 的元素就不需要多余操作。

代码

class Solution {
public:
    int minOperations(vector<int>& nums) {
        int cnt = 0, g = 0, n = nums.size();
        for (int i = 0; i < n; i ++ ) {
            if (nums[i] == 1) cnt ++ ;
            g = gcd(g, nums[i]);
        }
        if (g != 1) return -1;
        if (cnt > 0) return n - cnt; // 特殊情况
        int mn = n;
        for (int i = 0; i < n; i ++ ) {
            g = nums[i], cnt = 1; // 暴力查找 gcd = 1 的最短子数组
            for (int j = i + 1; j < n; j ++ ) {
                g = gcd(g, nums[j]);
                cnt ++ ;
                if (g == 1) {
                    mn = min(mn, cnt);
                    break;
                }
            }
        }
        return n + mn - 2;
    }
};

复杂度分析

时间复杂度:\(O(n^2)\);
空间复杂度:\(O(1)\)。

方法二:通过gcd性质优化

解题思路

通过迭代的方式计算子数组的 \(gcd\) 并进行去重优化(保持数组的连续性),注意 \(g\) 数组存储的元素含义。

class Solution {
public:
    int minOperations(vector<int>& nums) {
        int cnt = 0, res = 0, n = nums.size();
        for (auto &x : nums) {
            if (x == 1) cnt ++ ;
            res = gcd(res, x);
        }
        if (res != 1) return -1;
        if (cnt > 0) return n - cnt;
        vector<pair<int, int>> g; // {gcd, 相同的gcd的子数组最靠右边的左端点}
        int mn = n;
        for (int i = 0; i < n; i ++ ) {
            g.emplace_back(nums[i], i); // 添加
            int j = 0;
            for (auto &p : g) {
                p.first = gcd(p.first, nums[i]); // 相当于求 [p.second, i] 的 gcd
                if (p.first == g[j].first) { // 说明出现相同的 gcd,那么将靠右的左端点复制到 g[j],跳过 p
                    g[j].second = p.second;
                } else { // 说明出现不相同的 gcd 那么将 P move 到 ++ j 的位置,弥补数组空缺
                    g[ ++ j ] = move(p);
                }
            }
            g.resize(j + 1);
            if (g[0].first == 1) mn = min(mn, i - g[0].second + 1); // 第一个元素的 gcd 值一定最小,因为其结果是从开始到当前位置所有元素的 gcd
        }
        return n + mn - 2;
    }
};

复杂度分析

时间复杂度:\(O(nlogU)\),\(U = max(nums[0, n - 1])\);
空间复杂度:\(O(logU)\)。

标签:cnt,gcd,nums,int,c++,2654,++,数组
From: https://www.cnblogs.com/lxycoding/p/17409956.html

相关文章

  • c++打卡练习(33)
    歌星大赛,十个评委打分,去掉一个最高分,去掉一个最低分,求剩下的八个评分的平均分,作为选手的最终分数流程图:伪代码:源代码:#include<iostream>usingnamespacestd;intmain(){ inta[10],b[8]; inti,j,k,t,sum=0,Ave,max,min; cout<<"输入十个正整数"<<endl; for(i=0;i<10;i++){ ......
  • C++调用python过程+Anaconda使用arcpy包踩的坑
    C++调python(python文件包含第三方库):工具:VS2017QT5插件PycharmAnaconda1.下载Anaconda,配置一个虚拟环境2.将这个环境里的DLLs和Lib包以及相应py文件,放至C++项目生成.exe文件同级目录下 3.将include和libs放在项目某文件夹下,在VS里添加附加包含目录、附加库目录和附加依赖......
  • Mac 配置 OpenCV C++ 版本
    今天紀錄一下如何在Mac上安裝OpenCVforC++開發環境使用Brew安装,pkgconfig检测,2023.5.17Macx86(Intel),MacM1(Applesilicon)和Ubuntu也適用此筆記用OpenCV4.7.0_4版本做範例1.安装cmake与pkg-config如果您的 Mac 沒有cmake,pkg-config請先......
  • C++进阶学习(三)constexpr关键字、值类别与decltype关键字、lambda表达式
    五、constexpr说明符constexpr说明符声明该变量或函数在编译期进行求值,从而适用于需要编译器常量表达式的地方在变量声明constexpr时,对象或非静态成员函数蕴含const,函数或静态成员变量蕴含inlineconstexpr变量必须立刻被初始化constexprinta=5;//a=6;/*error*/......
  • C++
    复数类的运算#include<iostream>usingnamespacestd;classComplex{public:Complex(doubler=0,doublei=0):real(r),imag(i){}friendComplexoperator+(Complexc1,Complexc2)//重载双目运算符'+'{Complexc3;......
  • c++unique
    #include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>usingnamespacestd;intn,a[5211314],len;intmain(){ cin>>n; for(inti=1;i<=n;++i){ cin>>a[i]......
  • C++ 智能指针
    在介绍智能指针之前,先来看原始指针的一些不便之处:它的声明不能指示所指到底是单个对象还是数组。它的声明没有告诉你用完后是否应该销毁它,即指针是否拥有所指之物。如果你决定你应该销毁指针所指对象,没人告诉你该用delete还是其他析构机制(比如将指针传给专门的销毁函数)......
  • C++用代码验证“一切函数皆可傅里叶”
    #include<stdio.h>#include<math.h>#definepi3.1415926#definerows3#definecolums5typedefstruct{floatre;//reallyfloatim;//imaginary}complex,*pcomplex;complexcomplexadd(complexa,complexb)//复数加{comple......
  • c++ gdiplus实现屏幕截图
    #include<windows.h>#include<gdiplus.h>#include<iostream>#include<filesystem>#include<chrono>#include<iomanip>#include<sstream>#pragmacomment(lib,"Gdiplus.lib")usingnamespaceGdiplus;U......
  • 【C++ Primer】第二章(2 ~ 6节)
    变量变量提供一个具名的、可供程序操作的存储空间。C++中变量和对象一般可以互换使用。变量定义(define)定义形式:类型说明符(typespecifier)+一个或多个变量名组成的列表。如intsum=0,value,units_sold=0;初始化(initialize):对象在创建时获得了一个特定的值。初......