当前位置: 首页 > news >正文

【LeetCode 每日一题】2197. 替换数组中的非互质数

Problem: 2197. 替换数组中的非互质数

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N * log U)
    • 空间复杂度:O(N)

整体思路

这段代码旨在解决一个数组变换问题:给定一个整数数组 nums,需要不断地合并相邻的、不互质(最大公约数 > 1)的两个数,直到数组中任意相邻的两个数都互质为止。合并规则是将这两个数替换为它们的最小公倍数 (LCM)

该算法巧妙地利用了 栈 (Stack) 的思想来模拟这个合并过程。虽然代码中使用的是 ArrayList,但其 add(入栈)、getLast(窥视栈顶)、removeLast(出栈)等操作完全符合栈的“后进先出” (LIFO) 特性。

  1. 核心思想:栈式处理

    • 算法将最终的结果数组看作一个栈 st。它从左到右遍历输入的 nums 数组,逐个处理每个数 x
    • 当处理一个新数 x 时,它需要与栈顶的元素进行比较。如果它们不互质,就需要合并。合并后的新数可能会继续与新的栈顶元素不互质,所以这个合并过程需要持续进行,直到新数与栈顶元素互质,或者栈为空。
  2. 算法步骤

    • 初始化一个空的列表(作为栈)st
    • 遍历 nums 数组中的每一个元素 x
    • 对于每个 x,进入一个 while 循环:
      a. 检查条件!st.isEmpty() && gcd(x, st.getLast()) > 1。这个条件判断栈是否为空,以及当前数 x 是否与栈顶元素 st.getLast() 不互质。
      b. 合并操作:如果条件满足,说明需要合并。
      * int y = st.removeLast();:将栈顶元素 y 弹出。
      * x = (x / gcd(x, y) * y);:计算 xy 的最小公倍数 (LCM),并将结果赋给 x。这里使用了 lcm(x, y) = (|x * y|) / gcd(x, y) 的公式,为了防止溢出,写成了 (x / gcd(x, y)) * y 的形式。
      c. 循环继续:合并后得到的新 x,需要继续与新的栈顶元素进行比较,因此 while 循环会继续执行,直到 x 与栈顶互质或栈为空。
    • 入栈:当 while 循环结束后,说明当前的 x(可能是原始的 x,也可能是多次合并后的结果)已经可以安全地放在栈顶了。执行 st.add(x),将其压入栈中。
  3. gcd 辅助函数

    • 算法依赖于一个 gcd 函数来计算两个数的最大公约数 (Greatest Common Divisor)。
    • 代码中实现的是经典的欧几里得算法(辗转相除法),这是一个非常高效的计算最大公约数的方法。
  4. 返回结果

    • nums 数组中的所有元素都处理完毕后,栈 st 中剩下的元素就是最终的结果序列,将其返回。

完整代码

import java.util.ArrayList;
import java.util.List;class Solution {/*** 合并数组中所有不互质的相邻元素,直到任意相邻元素都互质。* @param nums 输入的整数数组* st.add(x);}return st;}/*** 使用欧几里得算法(辗转相除法)计算两个整数的最大公约数 (GCD)。* @param x 第一个整数* @param y 第二个整数* @return x 和 y 的最大公约数*/private int gcd(int x, int y) {// 循环直到余数为 0while (y != 0) {int temp = y;y = x % y; // 新的 y 是 x 除以 y 的余数x = temp; // 新的 x 是原来的 y}// 当 y 为 0 时,x 就是最大公约数return x;}
}

时空复杂度

  • Nnums 数组的长度。
  • Unums 数组中元素的最大值。

时间复杂度:O(N * log U)

  1. 外层循环for (int x : nums) 遍历 nums 数组一次,执行 N 次。
  2. 内层 while 循环
    • 这个循环的行为是“合并”式的。每次循环都会消耗掉栈顶的一个元素。
    • 在整个算法的生命周期中,一个元素最多被压入栈一次,也最多被弹出一次。
    • 因此,while 循环的总执行次数(在所有外层循环中累加)不会超过 N 次。
  3. gcd 函数
    • 欧几里得算法的复杂度与输入数值的对数成正比。计算 gcd(x, y) 的时间复杂度大约是 O(log(min(x, y)))
    • 在我们的算法中,每次调用 gcd,其参数都与输入中的数值或它们的LCM相关。我们可以用 U (输入最大值) 作为其复杂度的上界,即 O(log U)

综合分析
总的时间复杂度大致是 (外层循环和内层循环的总迭代次数) * (单次 gcd 的时间)。
由于总迭代次数是 O(N) 级别,每次迭代都可能调用 gcd,所以总的时间复杂度是 O(N * log U)

空间复杂度:O(N)

  1. 主要存储开销:算法使用了一个列表 st 来作为栈。
  2. 空间大小
    • 在最坏的情况下,如果 nums 数组中的所有元素都两两互质,那么 st 栈将会存储所有 N 个元素。
    • 因此,st 占用的空间与输入规模 N 成线性关系。
  3. gcd 函数gcd 函数是迭代实现的,只使用了常数个额外变量,空间复杂度是 O(1)。

综合分析
算法所需的额外空间主要由栈 st 决定。因此,其空间复杂度为 O(N)

http://www.dtcms.com/a/392048.html

相关文章:

  • 城市水资源与水环境:植被如何重塑地球水循环?
  • TransBench:阿里国际等推出的多语言翻译评测体系
  • Windows启动Minio服务
  • 技术原理与癌症筛查的适配性问题
  • 集合通信算法总结
  • AutoDL四周年 ,学会使用AutoDL
  • nginx如果启动失败怎么办?
  • linux使用gunzip来解压.gz文件
  • 硬件(十五)LCD
  • B3clf: 最新的精准预测药物血脑屏障透过能力的开源app
  • 第八章 惊喜10 分享+
  • SMMU 软件指南
  • [x-cmd] Windows 安装和使用 x-cmd 的方法
  • 17.渗透-.Linux基础命令(九)-Linux权限管理(chmod修改文件权限)
  • 测量交流电压,测量直流电压,兼容,ADC采样转换计算有效值
  • 红黑树封装实现map set
  • EMQX和MQTTX的安装
  • AI 大模型入门 四:检索增强生成(RAG),自动生成精准用例!
  • EDR与MITRE ATTCK 详解
  • 特征值和特征向量
  • Gridview:让 HPC 作业管理真正“看得见、点得着、跑得快”
  • C++/初识
  • 进一步理解自适应卡尔曼滤波(AKF)
  • 反馈循环的跨领域智慧:从控制工程到Pix2Pix
  • AI智能体如何开发工作流及注意事项
  • 电视插座工程量计算-图形识别秒计量
  • 1.1 进程与内存知识点总结
  • 深度学习-神经网络(下篇)
  • 检查 Nginx 是否启动的几种方法
  • CSS 创建漂亮的文字肖像