六月集训 第八日——前缀和

前言

今天算法的内容是:前缀和

一、最高频元素的频数

        元素的 频数 是该元素在一个数组中出现的次数。给你一个整数数组 nums 和一个整数 k 。在一步操作中,你可以选择 nums 的一个下标,并**将该下标对应元素的值增加 1
        执行最多 k 次操作后,返回数组中最高频元素的 最大可能频数

示例 1:

输入:nums = [1,2,4], k = 5
输出:3
解释:对第一个元素执行 3 次递增操作,对第二个元素执 2 次递增操作,此时 nums = [4,4,4] 。
4 是数组中最高频元素,频数是 3 。
示例 2:

输入:nums = [1,4,8,13], k = 5
输出:2
解释:存在多种最优解决方案:

  • 对第一个元素执行 3 次递增操作,此时 nums = [4,4,8,13] 。4 是数组中最高频元素,频数是 2 。
  • 对第二个元素执行 4 次递增操作,此时 nums = [1,8,8,13] 。8 是数组中最高频元素,频数是 2 。
  • 对第三个元素执行 5 次递增操作,此时 nums = [1,4,13,13] 。13 是数组中最高频元素,频数是 2 。
    示例 3:

输入:nums = [3,9,6], k = 2
输出:1

一、思路:

        (1)题目没有说明数组是否有序,所以先进行一个递增排序(方便之后操作)
        (2)因为可以任意分配k中数以增加数组中任意元素值,可从最小值开始分配并开始区间长度的增长~~(为什么从最小值开始呢?暂时还不是非常深入的清楚,就是挨个的运算吧)~~
        (4)所以可以从排序后区间数组的最短前缀和下标开始循环递增
        (5)对当前下标元素值和数组区间长度所乘得的理想数值(理想分配后的前缀和)与当前长度的实际大小进行一个相减(当前实际前缀和)设理想分配值 变量为 s,就可知该需要分配多少值,所以这是一个前缀和的问题
        (6)然后与可分配的 k 值进行比较可知够不分配,不够分配就需要右移左区间边界的位置,改变左边界直到s<=k为止(现在不够,之后也是不够的,左区间右移后不会再次归零),减少频数,所以这又是一个区间范围的问题
(有点像游戏里面的属性加点呐 hh)
综上所诉:
·(1)需要用到 前缀统计区间大小 与 计算部分和的知识
·(2)需要用到 双指针处理 边界的问题的知识

二、源码

class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        long long sum[101001];
        int i,j;
        int ans=0;
        int n=nums.size();
        for(i=1;i<=n;i++){
            sum[i]=sum[i-1]+nums[i-1];
        }
        i=0;
        for(j=1;j<=n;j++){
            long long s=(sum[j]-sum[j-1])*(j-i)-(sum[j]-sum[i]);
            while(s>k){
                i++;
                s=(sum[j]-sum[j-1])*(j-i)-(sum[j]-sum[i]);
            }
            ans=max(ans,j-i);
        }
        return ans;
    }
};
//英雄哥的代码啦hh
//争取有一天可以自己想出来hhh

三.知识点

        (1)需要用到 前缀统计区间大小 与 计算处理区间部分和的知识
        (2)需要用到 双指针处理 边界的知识

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值