数组变为有序的最小操作次数
难度:
标签:
题目描述
代码结果
运行时间: 30 ms, 内存: 16.1 MB
/*
题目思路: Java Stream实现变为有序数组的最小交换次数。此解决方案通过先排序然后计算原数组和排序后数组之间的交换次数来完成。
1. 将原数组索引和元素存为对,并按照元素排序。
2. 使用布尔数组跟踪已访问元素。
3. 计算形成的循环,并以此为基础计算交换次数。
*/
import java.util.stream.IntStream;
import java.util.Arrays;
public class Solution {
public int minSwaps(int[] nums) {
int n = nums.length;
int[] sorted = IntStream.range(0, n)
.boxed()
.sorted((i, j) -> Integer.compare(nums[i], nums[j]))
.mapToInt(i -> i)
.toArray();
boolean[] visited = new boolean[n];
int swaps = 0;
for (int i = 0; i < n; i++) {
if (visited[i] || sorted[i] == i) continue;
int cycleLength = 0;
int j = i;
while (!visited[j]) {
visited[j] = true;
j = sorted[j];
cycleLength++;
}
if (cycleLength > 0) swaps += cycleLength - 1;
}
return swaps;
}
}
解释
方法:
这道题的思路是使用贪心算法和优先队列(堆)。首先定义一个辅助函数 helper,它负责计算将数组变为单调递增所需的最小操作次数。遍历数组中的每个元素,对于每个元素,如果优先队列为空,则将其加入队列。如果队列不为空,则检查队列中的最大元素(队列是最大堆)是否大于当前元素,如果是,则将最大元素替换为当前元素,并将差值累加到结果中。这样做的目的是为了保持数组的单调递增性,同时减少操作次数。最后,返回将数组变为单调递增和单调递减的最小操作次数中的较小值。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
题解中为什么要分别计算数组变为单调递增和单调递减的最小操作次数,而不是只计算单一方向的变化?
▷🦆
在题解的`helper`函数中,为什么在发现前一个最大元素大于当前元素时,选择替换最大元素而不是进行其他操作?
▷🦆
题解提到使用最大堆来维护数组元素,堆中元素为什么使用负数表示,这样做有什么特别的考虑吗?
▷🦆
当最大元素被替换后,为什么还需要再次将当前元素加入到堆中?
▷