划分数组使最大差为 K
难度:
标签:
题目描述
代码结果
运行时间: 103 ms, 内存: 30.6 MB
/*
题目思路:
1. 对数组进行排序。
2. 使用Stream API来进行数组的遍历和处理。
3. 初始化一个变量用于记录子序列的数量。
4. 遍历排序后的数组,使用一个指针指向当前子序列的开始位置。
5. 对于每一个新的元素,如果它与当前子序列的最小元素的差值超过k,则创建一个新的子序列。
6. 返回子序列的数量。
*/
import java.util.Arrays;
public class Solution {
public int minSubsequences(int[] nums, int k) {
Arrays.sort(nums);
final int[] count = {1};
final int[] start = {0};
Arrays.stream(nums).skip(1).forEach(num -> {
if (num - nums[start[0]] > k) {
count[0]++;
start[0] = Arrays.binarySearch(nums, num);
}
});
return count[0];
}
public static void main(String[] args) {
Solution solution = new Solution();
int[] nums = {3, 6, 1, 2, 5};
int k = 2;
System.out.println(solution.minSubsequences(nums, k)); // 输出:2
}
}
解释
方法:
首先,题解通过转换列表为集合来去除任何重复元素,因为重复元素可以放在同一个子序列中而不影响最大值和最小值的差。然后,对去重后的数组进行排序,便于顺序比较元素。题解采用贪心算法的思想,从第一个元素开始,依次判断后一个元素与当前子序列最小元素的差是否大于k。如果大于k,意味着需要开始一个新的子序列,并将当前元素设为新子序列的最小元素;如果不大于k,则当前元素可以加入到当前子序列。通过遍历一次数组,可以确定需要的最少子序列数。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在处理前先将数组转换为集合再转回列表?这一转换对子序列的划分有什么影响?
▷🦆
在算法中,为什么选择排序后的数组来进行子序列的划分?直接在未排序的数组上操作是否可行?
▷🦆
题解中提到,如果当前元素与子序列的最小元素的差大于 k,则需要开始一个新的子序列。请问这种方法是否能保证总是得到最少的子序列数目?
▷🦆
在算法实现中,变量 `pre` 是如何使用的,它的作用是什么?
▷