數組小和-歸併排序

題目描述

給定一個數組arr,求arr每個位置arr[i]左邊≤arr[i]的數的和,最後返回每個位置的總和sum。
示例:
輸入:arr[] = {2,5,4,7}
輸出:sum = 15
sum[0] = 0
sum[1] = 2
sum[2] = 2
sum[3] = 2 + 5 + 4 = 11
sum = sum[0] + sum[1] + sum[2] + sum[3] = 15

解題思路
這題思路與反轉對類似
此題也是結合了歸併排序的思想,在merge的過程中因爲左右兩邊的數都已經拍好序所以對於每一個數我們求它右邊比他大的數的個數(通過下標變換),然後結合以求得當前位置的小和
代碼:

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

	public static int mergeSort(int[] arr, int l, int r) {
		if (l == r) {
			return 0;
		}
		int mid = l + ((r - l) >> 1);
		// 左邊的小和 + 右邊的小和 + merge過程中的小和
		return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r);
	}

	public static int merge(int[] arr, int l, int m, int r) {
		int[] help = new int[r - l + 1];
		int i = 0;
		int p1 = l;
		int p2 = m + 1;
		int res = 0;
		while (p1 <= m && p2 <= r) {
			res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; // 增加了這一行代碼
			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
		}
		while (p1 <= m) {
			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;
	}

時間複雜度:O( NlogN )
空間複雜度:O(N)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章