使数组元素相等的减少操作次数
难度:
标签:
题目描述
代码结果
运行时间: 121 ms, 内存: 26.5 MB
/*
* 思路:
* 1. 统计每个数的频率,并按从大到小排序。
* 2. 使用Java Stream API实现上面的逻辑。
*/
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
public class MakeElementsEqualStream {
public int reductionOperations(int[] nums) {
Map<Integer, Long> freq = Arrays.stream(nums)
.boxed()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()));
int[] uniqueNums = freq.keySet().stream().sorted().mapToInt(e -> e).toArray();
int operations = 0;
for (int i = uniqueNums.length - 1; i > 0; i--) {
operations += freq.get(uniqueNums[i]) * (i);
freq.put(uniqueNums[i - 1], freq.get(uniqueNums[i - 1]) + freq.get(uniqueNums[i]));
}
return operations;
}
public static void main(String[] args) {
MakeElementsEqualStream solution = new MakeElementsEqualStream();
int[] nums1 = {5, 1, 3};
System.out.println(solution.reductionOperations(nums1)); // 输出: 3
int[] nums2 = {1, 1, 1};
System.out.println(solution.reductionOperations(nums2)); // 输出: 0
int[] nums3 = {1, 1, 2, 2, 3};
System.out.println(solution.reductionOperations(nums3)); // 输出: 4
}
}
解释
方法:
这个题解首先将数组 nums 中的元素去重并排序,得到一个有序的不重复元素数组 s。然后,使用字典 dt 来映射每个元素在 s 中的索引,这个索引实际上表示的是,从最小值到当前值需要经过多少步骤才能使所有元素变得相等。例如,最小的元素映射到 0,表示不需要任何操作,第二小的元素映射到 1,表示需要一步操作使其降低到最小元素的级别,以此类推。最后,通过遍历原始数组 nums,并使用映射 dt 计算总的操作次数。每个元素的操作次数就是它对应的索引值。
时间复杂度:
O(n + u log u)
空间复杂度:
O(u)
代码细节讲解
🦆
为什么题解中要使用去重并排序的数组s来计算操作次数,而不是直接在原数组nums上操作?
▷🦆
在构建映射字典dt时,字典的值是如何确定的,即如何确定每个元素到最小元素的操作步骤数?
▷🦆
题解中提到的`从最小值到当前值需要经过多少步骤才能使所有元素变得相等`,这个步骤数是怎样计算的?
▷🦆
如果nums数组中的所有元素已经是相等的,题解的算法是否会进行不必要的计算?
▷