LeetCode 使循环数组所有元素相等的最少秒数

2024-01-31 15:52

本文主要是介绍LeetCode 使循环数组所有元素相等的最少秒数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

地址:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
难度:中等

题目描述:给你一个下标从 0 开始长度为 n 的数组 nums 。
每一秒,你可以对数组执行以下操作:

  • 对于范围在 [0, n - 1] 内的每一个下标 i ,将 nums[i] 替换成 nums[i] ,nums[(i - 1 + n) % n] 或者 nums[(i + 1) % n] 三者之一。

其实就是nums[i]可以替换成它本身或者它的前一位或者后一位的值,这个时候在想边缘怎么办?

把数组看出一个环,num[0]挨着的就是num[8]和num[1]
可以带入计算一下:n = 9 ,i = 0,
(i - 1 + n) % n = (0-1+9)%9 = 8
(i +1 + n) % n = (0+1+9)%9 = 10%9 = 1


注意,所有元素会被同时替换。

也就是一轮替换就是1s
比如可以同时操作num[1]、num[2])替换,等这一轮停止操作了我们得到了一个替换后的数组
入果这个数组没有符合预期,那就需要再进行到下一轮替换

请你返回将数组 nums 中所有元素变成相等元素所需要的 最少 秒数。

思考过程

可以理解为将数组的每一个元素都逐渐替换为数组中的某个值。
我们可以枚举数组中的各种元素,分别计算将所有元素替换为该元素所消耗的时间。
计算过程需要利用该元素在数组中出现的位置

题解

  • 我们首先用哈希表,统计 nums 中相同的数所出现的位置,mp[x]表示 x 所出现的位置。
  • 然后我们研究,使得数组全部变为 x所需要的时间,这个时间取决于 nums中,相邻 x 的最大距离。
  • 我们依次枚举所有相邻(包括头尾)x 的索引值,找到最大的距离。
  • 最大距离除以二并向上取整,就是使得数组全部变为 x 所需要的时间
  • 最后我们对所有 nums中 的数,都找到所需的时间,返回其中的最小值即可。

本质上是扩散的原理

假设现在数组的为 3 2 6 4 9 5 3 1,x是3

分析:
我们能看到两个3之间最大的间隔有5个元素,那需要经过多少轮才能把3之间的元素同步扩散完呢?

第一次扩散(暂时不要关注数字1):

第二次扩散(暂时不要关注数字1):

第三次扩散(暂时不要关注数字1):

可以看到是经过了三次才完成了扩散,正好是5/2在向上取整的结果

为什么是除2?
因为每次两边都能同时扩散推进一个,效率是乘2的,自然最后计算的时候也就是除2啦

那短距离的那边怎么统计呢?
题目说了:所有元素会被同时替换。
也就是说,元素的扩散是同时进行的,长的距离扩散的时候,短的距离也在同步扩散,那个1在第一轮扩散的时候就被替换成3了
时间长的都扩散完了,时间短的其实早就扩散完毕了

代码解析:

function minimumSeconds(nums: number[]): number {const n:number = nums.lengthlet rs:number = nconst mp:Map<number,number[]> = new Map() //存储结果for(let i:number = 0;i<n;i++){if (!mp.has(nums[i])) {mp.set(nums[i], []);}mp.get(nums[i]).push(i);}for(const pos of mp.values()){let mx: number = pos[0] + n - pos[pos.length - 1]-1;//为什么设置这个初始值?// 避免环形的时候最大距离计算错误for (let i: number = 1; i < pos.length; ++i) {mx = Math.max(mx, pos[i] - pos[i - 1]-1);}rs = Math.min(rs, Math.ceil(mx / 2));}return rs
};

解释一下这行代码:number = pos[0] + n - pos[pos.length - 1]-1

我们知道我们需要找到的是最大距离,记住数组是环形数组
那么下面的情况,最大长度就会是pos[0] + n - pos[pos.length - 1]-1

如果我们还是拿2-0-1的话,计算出来的是短的距离,结果是1,会导致最终的答案不对

这篇关于LeetCode 使循环数组所有元素相等的最少秒数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/664293

相关文章

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

Python判断for循环最后一次的6种方法

《Python判断for循环最后一次的6种方法》在Python中,通常我们不会直接判断for循环是否正在执行最后一次迭代,因为Python的for循环是基于可迭代对象的,它不知道也不关心迭代的内部状态... 目录1.使用enuhttp://www.chinasem.cnmerate()和len()来判断for

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W