【LeetCode 2808】使循环数组所有元素相等的最少秒数
题目描述
原题链接: LeetCode.2808 使循环数组所有元素相等的最少秒数
解题思路
- 每次变化可以选择变成前一个元素或后一个元素,包括 [0] 和 [n - 1] 的转化;
- 换个角度思考,每秒最多可以有两个不同元素nums[i-1]和nums[i+1]变化成nums[i]元素;
- 假设nums[i]元素只出现一次,想要将所有元素同化那么每秒只能同化两个,下一秒仍然只能从已同化区域的两端继续同化两个;
- 如果nums[i]元素值出现两次,这两次中间的不同元素个数为x,那么想要将x个元素全部同化就需要"x / 2"秒;
- 总结一下,每秒可以向两边同化2个不同元素,每个元素相邻两次出现的间距元素个数最大值除以2就是将数组全部同化的秒数;
- 因为是循环数组,所以还要考虑首尾分段的这种特殊间距情况。
解题代码
/**
* 哈希表记录元素下标集合,计算间距最大值得到变化所需次数
* 执行用时: 69 ms , 在所有 Java 提交中击败了 76.56% 的用户
* 内存消耗: 79.25 MB , 在所有 Java 提交中击败了 45.31% 的用户
*/
public int minimumSeconds(List<Integer> nums) {
if (nums == null || nums.size() < 2) {
return 0;
}
Map<Integer, List<Integer>> idxListMap = new HashMap<>();
int n = nums.size();
for (int i = 0; i < n; i++) {
idxListMap.computeIfAbsent(nums.get(i), a -> new ArrayList<>()).add(i);
}
if (idxListMap.size() < 2) {
// 原始数组元素全部相同
return 0;
}
int ans = n;
for (List<Integer> idxList : idxListMap.values()) {
// 计算相同元素的下标间距最大值,初始化为循环数组需要考虑的首尾两个下标间距值
int max = idxList.get(0) + n - idxList.get(idxList.size() - 1);
for (int i = 1; i < idxList.size(); i++) {
max = Math.max(idxList.get(i) - idxList.get(i - 1), max);
}
// 将数组变成当前元素值的次数为 max / 2
ans = Math.min(ans, max / 2);
}
return ans;
}
考虑到只需要计算相邻两次下标差值,没必要保存所有下标,可以进一步优化:
/**
*
* 执行用时: 47 ms , 在所有 Java 提交中击败了 93.75% 的用户
* 内存消耗: 61.35 MB , 在所有 Java 提交中击败了 96.88% 的用户
*/
public int minimumSeconds(List<Integer> nums) {
if (nums == null || nums.size() < 2) {
return 0;
}
/*
* arr[0]: key第一次出现的下标
* arr[1]: key值上一次出现的下标
* arr[2]: key值相邻两次出现的中间元素个数+1的最大值
*/
Map<Integer, int[]> map = new HashMap<>();
int n = nums.size();
for (int i = 0; i < n; i++) {
int[] arr = map.computeIfAbsent(nums.get(i), k -> new int[3]);
if (arr[2] == 0) {
// 第一次出现
arr[0] = arr[1] = i;
arr[2] = -1;
}
else {
arr[2] = Math.max(i - arr[1], arr[2]);
arr[1] = i;
}
}
if (map.size() < 2) {
// 原始数组元素全部相同
return 0;
}
int ans = n;
for (int[] arr : map.values()) {
// 循环数组情况下,元素第一次和最后一次出现的下标间距最大值可能由首尾两端形成
int max = Math.max(arr[2], arr[0] + n - arr[1]);
// 将数组变成当前元素值的次数为 max / 2
ans = Math.min(ans, max / 2);
}
return ans;
}
本文表述基于作者主观理解,如有错漏或歧义之处,欢迎评论指出沟通交流