第十四题:小和问题(Java)

版权声明:Please make the source marked https://blog.csdn.net/qq_31807385/article/details/86318425

题目:

小和问题:在一个数组中,每一个数左边比当前小的数累加起来,叫做这数组的小和,求一个数组的小和,如:

【1,3,4,2,5】

1左边比1 小的数,没有

3左边比3 小的数,1

4左边比4 小的数,1,3

2左边比2小的数,1

5左边比5小的数,1,3,4,2

所以小和是,1 + 1 + 1 + 2 + 3 + 3, + 4 = 16 

代码实现与分析:

package com.isea.brush;

/**
 * 小和问题:
 * 解题思路:利用归并排序的思想,假定左右补分都是有序的,然后在将左右部分merge有序
 * 在merge的过程中,计算小和
 */
public class SmallSum {

    public static void main(String[] args) {

    }

    public static int smallSum(int[] arr) {
        if (arr.length < 2 || arr == null) {
            return 0;
        }
        return mergeSort(arr, 0, arr.length - 1);
    }

    /**
     * 在L-R的范围内会产生多少小和
     * 这个过程,搜集左半部分的小和,右半部分的小和,加上左右merge的小和,也就是在每次merge的时候,计算小和
     *
     * @param arr
     * @param L
     * @param R
     * @return
     */
    private static int mergeSort(int[] arr, int L, int R) {
        if (L == R) {
            return 0;
        }
        int mid = L + (R - L) / 2;
        return mergeSort(arr, L, mid) +
                mergeSort(arr, mid + 1, R) +
                merge(arr, L, mid, R);
    }

    /**
     * 归并排序的过程中,merge的过程,左右两个指针,然后一个辅助数组,
     * 对比左右数组中元素的大小,将其填入到辅助数组中
     *
     * @param arr
     * @param L
     * @param mid
     * @param R
     * @return
     */
    private static int merge(int[] arr, int L, int mid, int R) {
        int[] help = new int[R - L + 1];
        int i = 0;
        int p1 = L;
        int p2 = mid + 1;
        int res = 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;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_31807385/article/details/86318425