您现在的位置是:首页 >技术教程 >[HOT 100] 2779. 数组的最大美丽值网站首页技术教程
[HOT 100] 2779. 数组的最大美丽值
简介[HOT 100] 2779. 数组的最大美丽值
1. 题目链接
2. 题目描述
给你一个下标从 0 开始的整数数组 nums
和一个 非负 整数 k
。
在一步操作中,你可以执行下述指令:
- 在范围
[0, nums.length - 1]
中选择一个 此前没有选过 的下标i
。 - 将
nums[i]
替换为范围[nums[i] - k, nums[i] + k]
内的任一整数。
数组的 美丽值 定义为数组中由相等元素组成的最长子序列的长度。
对数组 nums
执行上述操作任意次后,返回数组可能取得的 最大 美丽值。
注意:你 只 能对每个下标执行 一次 此操作。
子序列 定义是:经由原数组删除一些元素(也可能不删除)得到的一个新数组,且在此过程中剩余元素的顺序不发生改变。
3. 题目示例
示例 1 :
输入:nums = [4,6,1,2], k = 2
输出:3
解释:在这个示例中,我们执行下述操作:
- 选择下标 1 ,将其替换为 4(从范围 [4,8] 中选出),此时 nums = [4,4,1,2] 。
- 选择下标 3 ,将其替换为 4(从范围 [0,4] 中选出),此时 nums = [4,4,1,4] 。
执行上述操作后,数组的美丽值是 3(子序列由下标 0 、1 、3 对应的元素组成)。
可以证明 3 是我们可以得到的由相等元素组成的最长子序列长度。
示例 2 :
输入:nums = [1,1,1,1], k = 10
输出:4
解释:在这个示例中,我们无需执行任何操作。
数组 nums 的美丽值是 4(整个数组)。
4. 解题思路
这道题的关键在于,最大子数组的美丽值 可以通过 滑动窗口(双指针)技巧来实现。基本思路是:
- 排序:首先对数组进行排序,这样可以确保窗口内的元素是有序的。排序后,若某个子数组中的最大值与最小值的差值不超过
2 * k
,则说明该子数组内的所有元素的差值也必然符合条件。 - 滑动窗口:使用两个指针
left
和right
,right
用来扩展窗口,left
用来收缩窗口。通过动态调整窗口的大小,确保窗口内元素的差值不超过2 * k
。 - 更新答案:每次扩展右指针时,检查当前窗口是否符合条件,如果符合条件,更新最大长度。
5. 题解代码
class Solution {
public int maximumBeauty(int[] nums, int k) {
Arrays.sort(nums); // 对数组进行排序
int ans = 0, left = 0;
// 右指针遍历整个数组
for(int right = 0; right < nums.length; right++){
// 如果当前窗口内的最大值与最小值的差超过 2 * k,则收缩窗口
while(nums[right] - nums[left] > k * 2){
left++; // 移动左指针
}
// 更新答案,记录当前窗口的最大长度
ans = Math.max(ans, right - left + 1);
}
return ans; // 返回最大子数组长度
}
}
6. 复杂度分析
- 时间复杂度:
O(n log n)
,其中n
是数组nums
的长度。排序的时间复杂度为O(n log n)
,而滑动窗口的遍历时间复杂度为O(n)
。因此,总时间复杂度为O(n log n)
。 - 空间复杂度:
O(1)
,算法使用了常数的额外空间,除了输入数组外,不需要额外的空间。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。