题目描述补充
题目:给定一个整数数组 arr
,你可以交换任意两个相邻元素一次。请编写一个算法,找出使数组元素严格递增所需的最小交换次数。如果无法通过交换使得数组严格递增,则返回 -1
。
示例
- 输入:
arr = [3, 2, 3, 1]
- 输出:
2
- 解释:我们可以进行两次交换,先将
3
和2
交换,得到[2, 3, 3, 1]
,再将3
和1
交换,得到[2, 1, 3, 3]
,此时数组是严格递增的。
解题思路
这个问题可以通过动态规划(DP)来解决。我们需要维护两个DP数组:
minSwaps[i]
表示以arr[i]
结尾的严格递增序列所需的最小交换次数。prevIndex[i]
表示在形成以arr[i]
结尾的严格递增序列时,arr[i]
应该从哪个位置的前一个位置交换过来(即arr[i]
应该放在哪个位置以形成递增序列)。
PHP 示例代码
function minSwapsToSort(array $arr): int {
$n = count($arr);
$minSwaps = array_fill(0, $n, PHP_INT_MAX);
$prevIndex = array_fill(0, $n, -1);
$minSwaps[0] = 0;
for ($i = 1; $i < $n; $i++) {
// 不交换,继承前一个位置的最小交换次数
$minSwaps[$i] = $minSwaps[$i - 1] + ($arr[$i] <= $arr[$i - 1] ? 1 : 0);
$prevIndex[$i] = $i - 1;
// 尝试从之前的某个位置交换过来,找到最优解
for ($j = 0; $j < $i; $j++) {
if ($arr[$j] <= $arr[$i]) {
if ($minSwaps[$j] + ($i - $j - ($arr[$j] <= $arr[$prevIndex[$j]] ? 1 : 0)) < $minSwaps[$i]) {
$minSwaps[$i] = $minSwaps[$j] + ($i - $j - ($arr[$j] <= $arr[$prevIndex[$j]] ? 1 : 0));
$prevIndex[$i] = $j;
}
}
}
}
// 检查是否存在无法递增的情况
if ($minSwaps[$n - 1] == PHP_INT_MAX) {
return -1;
}
return $minSwaps[$n - 1];
}
// 测试
$arr = [3, 2, 3, 1];
echo minSwapsToSort($arr); // 输出 2
注意
- PHP 示例中,
PHP_INT_MAX
用于初始化minSwaps
数组,表示初始时假设无法通过交换得到递增序列。 - 这个问题的时间复杂度较高,因为它涉及到两层循环,内层循环需要遍历到当前位置之前的所有位置。对于大数据集,可能需要考虑优化或使用其他算法。
- 码小课网站中有更多关于算法和数据结构的分享,欢迎访问学习。