数组的最大美丽值

题目链接:leetcode:数组的最大美丽值
描述

给你一个下标从 0 开始的整数数组 nums 和一个 非负 整数 k 。
在一步操作中,你可以执行下述指令:
在范围 [0, nums.length - 1] 中选择一个 此前没有选过 的下标 i 。
将 nums[i] 替换为范围 [nums[i] - k, nums[i] + k] 内的任一整数。
数组的 美丽值 定义为数组中由相等元素组成的最长子序列的长度。
对数组 nums 执行上述操作任意次后,返回数组可能取得的 最大 美丽值。
注意:你 只 能对每个下标执行 一次 此操作。
数组的 子序列 定义是:经由原数组删除一些元素(也可能不删除)得到的一个新数组,且在此过程中剩余元素的顺序不发生改变。

输入

nums = [4,6,1,2], k = 2
1 <= nums.length <= 10^5
0 <= nums[i], k <= 10^5

输出

3

思路:
题目可以理解为nums[i]是一个范围为[ nums[i] - k, nums[i] + k]的区间,然后要求所有区间叠加后重复最多的元素个数是多少。
例如:
给定nums = [1, 3, 5], k = 2,那么按之前的理解nums[0]可以看做区间[-1, 3], nums[1]可看做[1, 5], nums[2]可看做[3, 7],这三个区间叠加后重复最多的元素是3,它重复了3次,所以最大美丽值为3。
nums[i]对应的区间可以O(1)得出,难点就在于区间的覆盖和重复元素统计。
由于nums[i]和k的范围均为[0, 10^5],不妨先从暴力方法入手。建立一个数组a,对于每个nums[i]对应的区间中的每个数都在a的对应位置+1,最后再遍历一遍数组a去寻找最大值。
这个思路在这里会出现两个问题:
1.总复杂度为O(n^2);
2.nums[i]-k会存在负值。
下面给出解决方案:
1.对于数组频繁的区间更新操作且只在更新完毕后查询数组所有元素一次,这个可以采用差分数组去完成,使得每次区间更新操作时间复杂度为O(1),更新完毕后查询最大值的时间复杂度为O(n),所以区间的覆盖和重复元素统计的时间复杂度为O(n),满足题目要求。
2.对于所有nums[i]-k < 0 的部分都可以用0代为表示,即[-3, a], [-6, b], [-9, c]与[0, a], [0, b], [0, c]的最大美丽值是一样的,因为nums[i]>=0, 区间有小于0的部分时,区间必然包含整数 0。

class Solution {
public:
    int maximumBeauty(vector<int>& nums, int k) {
        int mx_val = 0;
        for(int i = 0;i < nums.size();i++)
        {
            if(mx_val < nums[i])mx_val = nums[i];
        }
        vector<int> dx(mx_val+2);
        for(int i = 0;i < nums.size();i++)
        {
            int l = max(0, nums[i] - k)  , r = min(nums[i] + k, mx_val);
            dx[l]++;
            dx[r+1]--;
        }
        int ans = dx[0];
        for(int i = 1;i< mx_val;i++)
        {
            dx[i] += dx[i-1];
            ans = max(ans,dx[i]);
        }
        return ans;
    }
};

若有什么错误,欢迎指正^ _ ^ 。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值