Problem: 3010. 将数组分成最小总代价的子数组 I
文章目录
- [1. 整体思路](#1. 整体思路)
- [2. 完整代码](#2. 完整代码)
- [3. 时空复杂度](#3. 时空复杂度)
-
-
- [时间复杂度: O ( N log N ) O(N \log N) O(NlogN)](#时间复杂度: O ( N log N ) O(N \log N) O(NlogN))
- [空间复杂度: O ( log N ) O(\log N) O(logN)](#空间复杂度: O ( log N ) O(\log N) O(logN))
-
1. 整体思路
核心问题
我们需要将数组 nums 分成 3 个连续子数组,总代价是这 3 个子数组首元素的和。
算法逻辑
- 必选元素 :第一个子数组必须以
nums[0]开头,因此nums[0]必定计入总代价。 - 贪心选择 :为了使总代价最小,剩下的两个子数组的头元素必须是
nums剩余部分(即索引 1 到结尾)中最小的两个数。 - 局部排序 :
- 我们不需要对整个数组排序(因为
nums[0]的位置不能动)。 - 我们只需要对
nums从索引1开始的后缀进行排序。 - Java 的
Arrays.sort(array, fromIndex, toIndex)方法允许我们只对指定范围进行排序。
- 我们不需要对整个数组排序(因为
- 计算结果 :排序后,剩余部分的最小值变成了
nums[1],第二小变成了nums[2]。结果即为nums[0] + nums[1] + nums[2]。
2. 完整代码
java
import java.util.Arrays;
class Solution {
public int minimumCost(int[] nums) {
// 1. 局部排序
// Arrays.sort(array, fromIndex, toIndex) 对数组的特定范围进行排序
// fromIndex (包括): 1
// toIndex (不包括): nums.length
// 这一步操作后,nums[0] 保持原位不动,而 nums[1] 到最后的部分变成了升序排列
Arrays.sort(nums, 1, nums.length);
// 2. 计算最小代价
// nums[0]: 原数组的第一个元素 (固定必选)
// nums[1]: 剩下所有元素中的最小值
// nums[2]: 剩下所有元素中的第二小值
return nums[0] + nums[1] + nums[2];
}
}
3. 时空复杂度
假设数组 nums 的长度为 N N N。
时间复杂度: O ( N log N ) O(N \log N) O(NlogN)
- 计算依据 :
- 代码核心是对长度为 N − 1 N-1 N−1 的子区间进行排序。
Arrays.sort对于基本数据类型使用的是双轴快速排序(Dual-Pivot Quicksort),平均时间复杂度为 O ( N log N ) O(N \log N) O(NlogN)。
- 结论 : O ( N log N ) O(N \log N) O(NlogN)。
空间复杂度: O ( log N ) O(\log N) O(logN)
- 计算依据 :
- 相比上一版,这里没有使用
Arrays.copyOfRange创建新数组,节省了 O ( N ) O(N) O(N) 的堆空间。 - 但是,快速排序是递归实现的,需要消耗栈空间来存储递归调用的上下文。栈深度为 O ( log N ) O(\log N) O(logN)。
- 相比上一版,这里没有使用
- 结论 : O ( log N ) O(\log N) O(logN)。