小和問題(歸併排序的應用)

問題描述

在一個數組中, 每一個數左邊比當前數小的數累加起來, 叫做這個數組的小和。 求一個數組的小和。

樣例

[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+3+1+1+3+4+2=16

題解

  • 對數組進行歸併排序,在合併的過程中,如果左側部分的當前元素l小於右側部分的當前元素r,那麼計算右側部分當前位置到結束位置的元素個數,即爲兩部分合並之後的數組中在i右側的元素個數;否則右側指針下移。
  • 不會出現重複計算的情況,因爲每次都是各部分之間比較,內部並不進行比較。
public static int smallSum(int[] arr) {
		if(arr==null||arr.length<2)
			return 0;
		return smallSum(arr,0,arr.length-1);
	}
	private static int smallSum(int[] arr, int i, int j) {
		if(i==j)
			return 0;
		int mid=i+(j-i)/2;
		return smallSum(arr,i,mid)+smallSum(arr,mid+1,j)+mergeSum(arr,i,j,mid);
	}
	private static int mergeSum(int[] arr, int i, int j, int mid) {
		int s=0;
		int ii=i,ij=mid+1;
		int []help=new int[j-i+1];
		int k=0;
		while(ii<=mid&&ij<=j) {
			if(arr[ii]<arr[ij]) {
				s+=(j-ij+1)*arr[ii];
				help[k++]=arr[ii++];
			}else {
				help[k++]=arr[ij++];
			}
		}
		while(ii<=mid)
			help[k++]=arr[ii++];
		while(ij<=j)
			help[k++]=arr[ij++];
		for(k=0;k<help.length;k++) {
			arr[i+k]=help[k];
		}
		return s;
	}

應用2:在一個數組中, 左邊的數如果比右邊的數大, 則折兩個數構成一個逆序對, 請打印所有逆序對

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