小和问题(归并排序)

归并排序

小和问题

思路来源

一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到

笔记内容

  • 问题描述

    在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。

  • 算法思路

    1. 在该问题中,左边多少个比x小 ,分别把具体数组相加 = 右边n个比x大,加上 n * x
    2. 使用归并排序实现算法,由于算法原理,每个数只会跟在它右边的数进行一次比较。
    3. 若一个片段进行merge,我们需要四个变量分别统计片段最后一个数的下标,以及指针指向的当前下标。
    4. 由于两个数组已经是有序的,对于左数组,若当前指向数值小于右数组指向的数值,则说明从该指针开始后面的数都比左边指向的数值大,我们可以通过右数值指针和最大下标算出其个数,然后加入sum中。若左指针指向数值不小于右边的,则右边数组指针进行移动,并放入新的序列数组中。
  • 代码实现

    public class MergeSort {
        /**
         *归并排序
         *小和问题
         * */
        public static void main(String[] args) {
              int[] target = {1,3,4,2,5};
              int mid = (target.length-1)/2;
              int result = getResult(target,0,mid,mid+1,target.length-1);
            System.out.println(result);
        }
    
        public static int getResult(int[] target,int left1,int right1,int left2,int right2){
            int sum = 0;
            if(left1 == right1 && left2 == right2){
                if(target[left1] < target[left2]){
                    return target[left1];
                }
            }else if(left1 == right1){
                int mid2 = left2 + (right2 - left2) / 2;
                sum += getResult(target, left2, mid2, mid2 + 1, right2);
            }else if(left2 == right2){
                int mid1 = left1 + (right1 - left1) / 2;
                sum += getResult(target, left1, mid1, mid1 + 1, right1);
            }else {
                int mid1 = left1 + (right1 - left1) / 2;
                int mid2 = left2 + (right2 - left2) / 2;
                sum += getResult(target, left1, mid1, mid1 + 1, right1);
                sum += getResult(target, left2, mid2, mid2 + 1, right2);
            }
                int point1 = left1;
                int point2 = left2;
                int[] temp = new int[target.length];
            for (int i = 0; i < target.length; i++) {
                temp[i] = target[i];
            }
                int count = left1;
                while (point1 <= right1 && point2 <= right2) {
                    if (target[point1] >= target[point2]) {
                        temp[count] = target[point2];
                        point2++;
                    } else {
                        sum += target[point1] * (right2 - point2 + 1);
                        temp[count] = target[point1];
                        point1++;
                    }
                    count++;
                }
                if (point1 < right1) {
                    while (point1 < right1) {
                        temp[count] = target[point1];
                        point1++;
                        count++;
                    }
                }
                if (point2 <= right2) {
                    while (point2 < right2) {
                        temp[count] = target[point2];
                        point2++;
                        count++;
                    }
                }
            target = temp;
            return sum;
        }
    }
    
    
posted @ 2023-12-19 11:38  Noule  阅读(27)  评论(0编辑  收藏  举报