当前位置:   article > 正文

左神基础班01、计算数组的小和_求数组小和

求数组小和

题目描述:

数组小和的定义如下:

     例如,数组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的小和。要求时间复杂度为O(nlogn),空间复杂度为O(n)。

输入描述:

第一行有一个整数N。表示数组长度
接下来一行N个整数表示数组内的数

输出描述:

一个整数表示答案

示例1:

输入
6
1 3 5 2 4 6
输出
27

备注:
1⩽ N ⩽10^5
-100⩽ arr[i] ⩽ 100

原题链接:计算数组的小和

解题思路:

1、归并排序 + 递归:

      可以利用归并排序的思想,基本过程和归并排序一样,只不过在合并两个子数组时计算小和即可。设两个排好序的子数组分别为arr[l,mid]和arr[mid + 1,l],指针p1和p2分别指向左右子数组中的元素。具体的计算小和过程如下:

(1)当arr[p1] <= arr[p2]时,则计算小和,计算方式为res += (r - p2 + 1) * arr[p1],并将arr[p1]赋值给辅助数组help: help[i++] = arr[p1]

(2)当arr[p1] > arr[p2]时,则不用计算小和,直接将arr[p2]赋值给辅助数组help: help[i++] = arr[p2]

递归终止条件:l == r,返回0。

注:(1)当左边子数组中的元素等于右子数组的元素时,也要计算小和,因为这是题目的要求;(2)返回时最好使用long类型,防止数据溢出。

时间复杂度和空间复杂度: 时间复杂度为O(NlogN),空间复杂度为O(N)

实现代码:

import java.util.*;
public class Main{
	//解法1: 归并排序 + 递归
    public static long smallSumMerge(int[] arr, int l, int r){
        if(l == r || arr.length < 2)
            return 0;
        int mid = l + ((r - l) >> 1);//注意括号
        return smallSumMerge(arr, l, mid)
                + smallSumMerge(arr, mid + 1, r) + merge(arr, l, mid, r);
    }

    public static long merge(int[] arr, int l, int mid, int r){
        int[] help = new int[r - l + 1];
        long res = 0;
        int p1 = l, p2 = mid + 1;
        int i = 0;
        while(p1 <= mid && p2 <= r){
            //左边的数等于右边的数也算是一个小和
            res += arr[p1] <= arr[p2] ? arr[p1] * (r - p2 + 1) : 0;
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
        }
        while(p1 <= mid){
            help[i++] = arr[p1++];
        }
        while(p2 <= r){
            help[i++] = arr[p2++];
        }
        for(i = 0; i < help.length; ++i)
            arr[l + i] = help[i];
        return res;
    }

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n];
        for(int i = 0; i < n; ++i)
            arr[i] = sc.nextInt();
        System.out.println(smallSumMerge(arr, 0, n - 1));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/227491
推荐阅读
相关标签
  

闽ICP备14008679号