数组单调和

本文介绍了一种利用归并排序思路解决数组单调和问题的方法,通过比较子数组元素并累加符合条件的元素数量,实现了时间复杂度为O(n log n)的解决方案。以数组[1,3,5,2,4,6]为例,详细阐述了计算过程,最终得到单调和为27。" 118636259,11233351,Java后台无驱动PDF打印技术实现,"['Java开发', 'PDF处理', '后台服务', '打印技术', '服务器运维']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

         现定义数组单调和为所有元素i的f(i)值之和。这里的f(i)函数定义为元素i左边(不包括其自身)小于等于它的数字之和。请设计一个高效算法,计算数组的单调和。
给定一个数组A同时给定数组的大小n,请返回数组的单调和。保证数组大小小于等于500,同时保证单调和不会超过int范围。
测试样例:
[1,3,5,2,4,6],6
返回:27

         思路:暴力解法是采用双层循环,时间复杂度是o(n^2),空间复杂度是o(1)。

                     为降低时间复杂度,我们可以借助归并排序的思想:在每次递归过程中,我们只需将前半部分的元素和后半部分的元素相比较,如果前面的数值较小,则使单调和增加该值乘以后半部分中与该较小值相比较的那个数以后(包过自己)数值的个数即可。以数组[1,3,5,2,4,6]为例,如图所示,当递归到最底层的时候开始计算单调和sum(初始化为0),步骤如下:


         第一步:  比较子数组[1]与[3],因为1<3,所以单调和加1,即sum=0+1=1。

         第二步:  比较子数组[2]与[4],因为2<4,所以单调和加2,即sum=1+2=3。

        第三步:  比较子数组[1,3]与[5],因为1<5,所以单调和加1,即sum=3+1=4,因为3<5,所以单调和加3,即sum=4+3=7。

        第四步:  比较子数组[2,4]与[6],因为2<6,所以单调和加2,即sum=7+2=9,因为4<6,所以单调和加4,即sum=9+4=13。

       第五步:  比较子数组[1,3,5]与[2,4,6],因为1<2,所以单调和加1*3,即sum=13+3=16,因为2<3<6,所以单调和加3*2,即sum=16+6=22,因为4<5<6,所以单调和加5*1,即sum=22+5=27。

       相关代码如下:   

class MonoSum {
public:
    int merge(vector<int> &source,vector<int> &temp,int start,int end){
        if(start==end){
            temp[start]=source[start];
            return 0;
        }
        int mid=(start+end)/2;
        int id=start;
        int sum=0;
        int left=merge(temp,source,start,mid);
        int right=merge(temp,source,mid+1,end);
        int i=start,j=mid+1,k=start;
        while(i!=mid+1&& j!=end+1){
            if(source[i] <= source[j]){
                sum+=source[i]*(end-j+1);
                temp[id++]=source[i++];
            }
            else 
                temp[id++]=source[j++];
        }
        while(i!=mid+1)
            temp[id++]=source[i++];
        while(j!=end+1)
            temp[id++]=source[j++];
        return sum+left+right;
    }
    int calcMonoSum(vector<int> A, int n) {
        // write code here
        vector<int> temp(A);
        return merge(A,temp,0,n-1);
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值