计算数组的小和

计算数组的小和

java 复制代码
import java.util.Arrays;
/**
 * @title CalculationArrayXiaoHe
 * @description 计算数组小和 https://www.nowcoder.com/practice/edfe05a1d45c4ea89101d936cac32469
 * 描述
 * 例如,数组 s = [1, 3, 5, 2, 4, 6] ,
 * 在 s[0] 的左边小于或等于 s[0] 的数的和为 0 ; 在 s[1] 的左边小于或等于 s[1] 的数的和为 1 ;
 * 在 s[2] 的左边小于或等于 s[2] 的数的和为 1+3=4 ;  在 s[3] 的左边小于或等于 s[3] 的数的和为 1 ;
 * 在 s[4] 的左边小于或等于 s[4] 的数的和为 1+3+2=6 ;在 s[5] 的左边小于或等于 s[5] 的数的和为 1+3+5+2+4=15 。
 * 所以 s 的小和为 0+1+4+1+6+15=27
 * 给定一个数组 s ,实现函数返回 s 的小和
 * 输入描述:
 * 第一行有一个整数N。表示数组长度
 * 接下来一行N个整数表示数组内的数
 * 输出描述:
 * 一个整数表示答案
 * author zzw
 * version 1.0.0
 * create 2024/10/28 22:32
 **/
public class CalculationArrayXiaoHe {

    public static void main(String[] args) {
        int[] arr = {1, 3, 5, 2, 4, 6};
        arr = new int[]{5, 5, 5, 5, 5};
        long result = smallSum(arr, 0, arr.length - 1);
        System.out.println(result);
        System.out.println(Arrays.toString(arr));
    }

    public static long smallSum(int[] arr, int l, int r) {
        if (l == r) {
            return 0;
        }
        int m = l + (r - l) / 2;
        return smallSum(arr, l, m) + smallSum(arr, m + 1, r) + merge(arr, l, m, r);
    }


    /**
     * 返回跨左右产生的小和累加和。左侧有序、右侧有序,让左右有序
     * arr[l ... m] arr[m+1 ... r]
     *
     * @param arr 处理中的数组
     * @param l   左侧数组起始位置
     * @param m   左侧数组终止位置 ,m+1 右侧数据起始位置
     * @param r   右侧数据终止位置
     * @return 数组从l到r的小和
     */
    public static long merge(int[] arr, int l, int m, int r) {
        //
        long result = alculateCumulativeSum(arr, l, m, r);
        orderedArrayMerging(arr, l, m, r);
        return result;
    }

    /**
     * 计算数组arr中子数组 arr[l ... r] 的累加和
     *
     * @param arr 处理中的数组
     * @param l   左侧数组起始位置
     * @param m   左侧数组终止位置 ,m+1 右侧数据起始位置
     * @param r   右侧数据终止位置
     * @return 数组从l到r的小和
     */
    public static long alculateCumulativeSum(int[] arr, int l, int m, int r) {
        // 默认右侧数组的第一位的小和sum为0

        // 从右侧数组的第一位开始,从左侧数组的第一位开始进行比较,
        // 如果右侧数组的数字大于等于左侧的数字,则将sum加上左侧数组当前下标的值
        // 如果左侧数组的下标移动到了大于右侧数组处理下标处的数字或者移出了左侧数组的边界,将sum累加到ans上。
        // 将右侧数组下标向后移动一位

        long ans = 0;
        int sum = 0;
        for (int i = m + 1, j = l; i <= r; i++) {
            for (; j <= m && arr[j] <= arr[i]; j++) {
                sum += arr[j];
            }
            ans += sum;
        }

        return ans;
    }

    /**
     * 数组中的连续的两个有序部分进行合并
     *
     * @param arr 处理中的数组
     * @param l   左侧数组起始位置
     * @param m   左侧数组终止位置 ,m+1 右侧数据起始位置
     * @param r   右侧数据终止位置
     */
    public static void orderedArrayMerging(int[] arr, int l, int m, int r) {
        int ls = l;
        int rs = m + 1;
        int i = 0;

        int[] tmpArr = new int[r - l + 1];
        while (ls <= m && rs <= r) {
            tmpArr[i++] = arr[ls] <= arr[rs] ? arr[ls++] : arr[rs++];
        }

        while (ls <= m) {
            tmpArr[i++] = arr[ls++];
        }

        while (rs <= r) {
            tmpArr[i++] = arr[rs++];
        }

        for (int j = l; j <= r; j++) {
            arr[j] = tmpArr[j - l];
        }
    }

}
相关推荐
董董灿是个攻城狮6 分钟前
AI 视觉连载1:像素
算法
爬山算法36 分钟前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
智驱力人工智能37 分钟前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
kfyty7251 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎1 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄1 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
忆~遂愿1 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
小韩学长yyds1 小时前
Java序列化避坑指南:明确这4种场景,再也不盲目实现Serializable
java·序列化
仟濹1 小时前
【Java基础】多态 | 打卡day2
java·开发语言
孞㐑¥1 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法