**(不会)数据结构--小和问题 逆序对问题
小和问题
在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组的小和。
例子:
[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
解:利用归并排序中,在进行两部分小组合并时,会在对比时,如果左边的比右边的小,则加上 右边个数个的左边的数 num * (right - y + 1)
其中的某一次对比
求小和只发生在两个小组之间。
public class LittleSum { public int littleSum(int [] arrays){ return mergeSort(arrays, 0, arrays.length - 1); } public int mergeSort(int[] arrays, int left, int right){ if(left >= right){ return 0; } int mid = left + ((right - left) >> 1); return mergeSort(arrays, left, mid) + mergeSort(arrays, mid + 1, right) + merge(arrays, left, mid, right); } public int merge(int[] arrays, int left, int mid, int right){ int sum = 0; int[] help = new int[right - left + 1]; int i = 0; int x = left, y = mid + 1; while(x <= mid && y <= right){ sum += arrays[x] < arrays[y] ? arrays[x] * (right - y + 1) : 0; help[i++] = arrays[x] < arrays[y] ? arrays[x++] : arrays[y++]; } while(x <= mid){ help[i++] = arrays[x++]; } while(y <= right){ help[i++] = arrays[y++]; } i = 0; while(i < help.length){ arrays[left + i] = help[i++]; } return sum; } public static void main(String[] args){ int[] arrays = {1, 3, 4, 2, 5}; LittleSum littleSum = new LittleSum(); int sum = littleSum.littleSum(arrays); System.out.println(sum); } }
逆序对问题
在一个数组中, 左边的数如果比右边的数大, 则折两个数构成一个逆序对, 请打印所有逆序对
解:逆序对的同理,在merge的过程中,比较相应的两个数,遇到arrays[x] > arrays[y] 则从x开始,到mid结束,都比arrays[y]大,都可以构成逆序对,所以只需要将它们输出即可
与小和相比,只有第一个while处不同,其余地方均没有改动
public void merge(int[] arrays, int left, int mid, int right){ int[] help = new int[right - left + 1]; int i = 0; int x = left, y = mid + 1; while(x <= mid && y <= right){ if(arrays[x] > arrays[y]){ for(int j = x; j <= mid; j++){ System.out.println(arrays[j] + " " + arrays[y]); } help[i++] = arrays[y++]; } else{ sum += arrays[x] * (right - y + 1); help[i++] = arrays[x++]; } } while(x <= mid){ help[i++] = arrays[x++]; } while(y <= right){ help[i++] = arrays[y++]; } i = 0; while(i < help.length){ arrays[left + i] = help[i++]; } }
剑指offer中的逆序对:会有大小,溢出的问题,用int类型,会溢出,要用long型才可以
public class Solution { public int InversePairs(int [] array) { if(array == null || array.length == 0) return 0; long res = mergeSort(array, 0, array.length - 1); return (int)(res % 1000000007); } public long mergeSort(int[] array, int left, int right){ if(left >= right){ return 0; } int mid = ((right - left) >> 1) + left; return mergeSort(array, left, mid) + mergeSort(array, mid + 1, right) + merge(array, left, mid, right); } public long merge(int[] array, int left, int mid, int right){ int[] help = new int[right - left + 1]; int i = left, j = mid + 1, flag = 0; long res = 0; while(i <= mid && j <= right){ if(array[i] < array[j]){ help[flag++] = array[i++]; }else { help[flag++] = array[j++]; res = res + (mid - i + 1); } } while(i <= mid){ help[flag++] = array[i++]; } while(j <= right){ help[flag++] = array[j++]; } for(i = 0; i < flag; i++){ array[left + i] = help[i]; } return res; } }