Calculate the minimum sum of the array

topic

The definition of the small sum of the array is as follows:
For example, in the array s = [1, 3, 5, 2, 4, 6],
the sum of the numbers less than or equal to s[0] to the left of s[0] is 0;
in s[ The sum of the numbers less than or equal to s[1] on the left side of 1] is 1; the sum of the numbers
less than or equal to s[2] on the left side of s[2] is 1+3=4;
on the left side of s[3] The sum of numbers less than or equal to s[3] is 1;
the sum of numbers less than or equal to s[4] on the left side of s[4] is 1+3+2=6;
on the left side of s[5] is less than or The sum of the numbers equal to s[5] is 1+3+5+2+4=15.
So the small sum of s is 0+1+4+1+6+15=27.
Given an array s, the realization function returns the small sum of s
[Required] The time complexity is O(nlogn), and the space complexity is O( n)
Title link

Ideas

The realization of merging is not difficult. The difficult thing is why it can be done by merging. This requires thinking in a different direction.

For each number, what we need is the sum of all the numbers on its left side that are less than or equal to it. Find the sum of all the numbers. Then add up to get the result.
If we only look at the result, we can find that if s[i]the number on the right is greater than it n个, then the contribution of this number in the final result is n * s[i].


For example, the example of the title description. The
sum of numbers less than or equal to s[1] on the left side of s[1] is 1;
the sum of numbers less than or equal to s[2] on the left side of s[2] is 1+3=4 ;
in s left [3] is less than or equal to s [3] of the number of and is 1;
on the left of s [. 4] is less than or equal to s [. 4] the number is 1 + 3 + 2 = 6;
in The sum of the numbers on the left side of s[5] is less than or equal to s[5] is 1+3+5+2+4=15.


can be seenThere are five numbers on the right side of s[0] greater than or equal to it, So it s[0]was added five times,There are three numbers on the right side of s[1] greater than or equal to it, So it s[1]was added three times. It's the same behind. Therefore, in the process of merging, you can find s[i]how many of the right is greater than or equal to it each time .

import java.util.*;

/**
 * @author 香榭的落叶
 */
public class Main {
    
    
  public static void main(String[] args) {
    
    
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int[] arr = new int[n], temp = new int[n];
    for (int i = 0; i < arr.length; i++) {
    
    
      arr[i] = sc.nextInt();
    }
    System.out.println(mergeSort(arr, 0, n - 1, temp));
  }

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

  static long merge(int[] arr, int l, int mid, int r, int[] temp) {
    
    
    int i = l, j = mid + 1;
    long ret = 0;
    int idx = l;
    while (i <= mid && j <= r) {
    
    
      //之前在这有一个疑问,归并的时候[l, mid],[mid + 1, r]肯定是有序的
      //为什么计算结果的时候不加上[i + 1, mid]这一段
      ret += arr[i] <= arr[j] ? (r - j + 1) * arr[i] : 0;
      temp[idx++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
    }
    while (i <= mid) temp[idx++] = arr[i++];
    while (j <= r) temp[idx++] = arr[j++];
    //参数含义:src, srcPos, dest, destPos, len
    System.arraycopy(temp, l, arr, l, r - l + 1);
    return ret;
  }
}

After thinking about it carefully, the previous paragraph was already calculated during the recursive sub-process.
Such as arrays arr = [1, 3, 5, 2, 4]. Its child process when recursion as follows:
[1, 3, 5], [2, 4]
[1, 3] [5], [2], [4]
[1],[3] [5]
in [1],[3]the process of calculation of the merge has been too small and 3, the [1, 3] 与 [5]merge time plus 3 does not need. That is, each time when merging, the two larger segments are merged, and at this time [i + 1, mid]this segment has been accumulated in the previous round of merging.

Guess you like

Origin blog.csdn.net/qq_42007742/article/details/109293886