leetcode
leetcode 2401 ~ 2450
使循环数组所有元素相等的最少秒数

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

难度:

标签:

题目描述

You are given a 0-indexed array nums containing n integers.

At each second, you perform the following operation on the array:

  • For every index i in the range [0, n - 1], replace nums[i] with either nums[i], nums[(i - 1 + n) % n], or nums[(i + 1) % n].

Note that all the elements get replaced simultaneously.

Return the minimum number of seconds needed to make all elements in the array nums equal.

 

Example 1:

Input: nums = [1,2,1,2]
Output: 1
Explanation: We can equalize the array in 1 second in the following way:
- At 1st second, replace values at each index with [nums[3],nums[1],nums[3],nums[3]]. After replacement, nums = [2,2,2,2].
It can be proven that 1 second is the minimum amount of seconds needed for equalizing the array.

Example 2:

Input: nums = [2,1,3,3,2]
Output: 2
Explanation: We can equalize the array in 2 seconds in the following way:
- At 1st second, replace values at each index with [nums[0],nums[2],nums[2],nums[2],nums[3]]. After replacement, nums = [2,3,3,3,3].
- At 2nd second, replace values at each index with [nums[1],nums[1],nums[2],nums[3],nums[4]]. After replacement, nums = [3,3,3,3,3].
It can be proven that 2 seconds is the minimum amount of seconds needed for equalizing the array.

Example 3:

Input: nums = [5,5,5,5]
Output: 0
Explanation: We don't need to perform any operations as all elements in the initial array are the same.

 

Constraints:

  • 1 <= n == nums.length <= 105
  • 1 <= nums[i] <= 109

代码结果

运行时间: 119 ms, 内存: 43.4 MB


// Java Stream Solution
// Similar to the previous Java solution but utilizing Java Streams for a more concise approach.
// We count the frequency of each element using a HashMap and find the maximum frequency.
// The result is the difference between the length of the array and the maximum frequency of any element.

import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class StreamSolution {
    public int minSecondsToEqual(int[] nums) {
        Map<Integer, Long> countMap = Arrays.stream(nums)
            .boxed()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        long maxFreq = countMap.values().stream().max(Long::compare).orElse(0L);
        return (int) (nums.length - maxFreq);
    }
}

解释

方法:

该题解的思路是首先统计数组中每个不同元素的最左出现位置(leftMost)和最右出现位置(rightMost),然后对于每个元素计算其在数组中的所有相邻出现位置之间的距离,并将这些距离存储在一个字典(dist)中。最后,对于每个元素,将其最左出现位置到最右出现位置的距离也加入到dist中。这样,对于每个元素,dist中存储的就是将其转换为相同元素所需的最小步数的候选值。最后,遍历dist,找到最小的最大距离,即为所需的最小秒数。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中,为什么要统计每个元素的最左和最右出现位置?这对解题有什么帮助?
在题解中,统计每个元素的最左和最右出现位置帮助确定元素在数组中分布的范围。这是因为要使数组所有元素相等,我们需要考虑将数组的一部分或全部转变为同一个元素。知道元素的最左和最右出现位置,可以帮助我们计算如果选择该元素作为目标值,需要覆盖的最长连续子数组的长度。这样,我们可以更准确地估计出使整个数组元素相等的最少操作次数。
🦆
题解中提到的距离存储字典(dist)的结构是如何设计的?能否详细解释这个字典中各个键值对的意义?
在题解中,距离存储字典(dist)的键是数组中的元素,而值是一个列表,这个列表存储的是该元素的所有相邻出现位置之间的距离,以及从最左出现位置到最右出现位置的循环距离。例如,如果某个元素在索引2, 5, 9出现过,dist将会记录从5到2的距离,从9到5的距离,以及从2回到9的循环距离。这样的结构帮助识别将数组中的所有元素转换为此元素时,每个转换步骤中必须覆盖的最大距离,从而确定最优的转换策略。
🦆
如何理解题解中提到的将最左出现位置到最右出现位置的距离也加入到dist中这一操作?这样做的目的是什么?
将最左出现位置到最右出现位置的距离加入到dist中是为了考虑循环数组的特性。在循环数组中,数组的末端元素可以直接与数组的起始元素相邻。因此,计算从最左出现位置到最右出现位置的距离,实际上是计算闭合循环的一部分,即从最右边的元素跳转到最左边的元素所需覆盖的距离。这样做可以确保在计算所有元素转换为同一元素时,考虑到数组的循环性,从而找到覆盖整个数组所需的最小最大步数。
🦆
题解中最终返回的结果为什么要进行(ans//2)操作?这一步的数学逻辑和目的是什么?
题解中进行(ans//2)操作的原因是,在计算距离时,每次计算的是从一个元素到另一个相同元素的距离,这实际上是两个步骤的距离(即从一个位置移动到下一个位置,然后再移动到下一个相同元素的位置)。因此,为了得到将所有元素变为相同元素所需的实际秒数(即操作次数),需要将累计的距离除以2,从而得到单次操作的平均最大距离,这是因为每次操作可以同时改变两个位置的元素。

相关问题