当前位置:   article > 正文

求一个数组的小和_求数列的小和

求数列的小和

问题描述

在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例:求数组[1,3,4,2,5]的小和。

1左边比1小的数,没有;3左边比3小的数,1;4左边比4小的数,13;2左边比2小的数,1;5左边比5小的数,1342;所以小和为1 + 1+3 + 1 + 1+3+4+2=16

思路概括

     * 利用归并排序的思想可以降低时间复杂度
     * 求小和的逆向思维,举例来说:小和的算法等价于找出1右边比1大的数的个数是4,则整个数组的小和增加1*4;3的右边有2个数比3大,则整个数组的小和增加3*2;4的右边比4大的有1个数,则整个数的小和增加4*1;2的右边比2大的数有1个,则小和增加2*1,5的右边没有比5大的数。
     * 求一个数的右边有多少个数比它大,就可以用归并排序的思路来完成
     * 采用递归的方式,在归并的过程中,一边排序,一边计算小和

代码实现

  1. public static int smallSum(int[] arr){
  2. //数组长度小于2时,小和为0
  3. if(arr == null || arr.length < 2){
  4. return 0;
  5. }
  6. return process(arr, 0, arr.length-1);
  7. }
  8. /**
  9. * 求小和的主体实现部分
  10. */
  11. private static int process(int[] arr, int L, int R) {
  12. if(L == R){
  13. return 0; //如果只有一个数,则不会产生小和
  14. }
  15. int sum = 0; //用于累加小和
  16. int mid = L + ((R - L) >> 1); //中间位置
  17. sum += process(arr, L, mid); //累加左侧排序求小和的结果
  18. sum += process(arr, mid+1, R); //累加右侧排序求小和的结果
  19. sum += merge(arr, L, mid, R); //累加归并左右两部分时产生小和的结果
  20. return sum;
  21. }
  22. /**
  23. * 关键:既要排序,又要求小和,
  24. * 并且当左组与右组的元素值相等时,一定要先拷贝右组的值(即让右指针先移动),这也是与标准的mergeSort的区别
  25. * 这样才能确定产生的小和个数。
  26. * 为什么需要排序:因为在合并的过程中排序后,在下一次合并计算小和的时候更加方便,且不会遗漏重复。
  27. */
  28. private static int merge(int[] arr, int L, int mid, int R) {
  29. int sum = 0; //用于累加小和
  30. int help[] = new int[R - L + 1];
  31. int p1 = L;
  32. int p2 = mid+1;
  33. int i = 0; //help的下标指针
  34. while(p1<=mid && p2 <=R){ //当两个下标都没有越界
  35. /*if(arr[p1] < arr[p2]){ //当左边部分的数小于右边部分的数时,产生小和arr[p1] * (R-p2+1)
  36. help[i++] = arr[p1];
  37. sum += arr[p1] * (R - p2 + 1);
  38. p1++; //左指针右移
  39. }else{//如果右组的数小于等于左组的数,则不产生小和,只是复制该值,并将右指针右移
  40. help[i++] = arr[p2++];
  41. }*/
  42. //以上的代码的优化
  43. sum += arr[p1] < arr[p2] ? arr[p1] * (R - p2 + 1) : 0;
  44. help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
  45. }
  46. //以下两个情况,至多存在一种
  47. while(p1 <= mid){
  48. help[i++] = arr[p1++];
  49. }
  50. while(p2 <= R){
  51. help[i++] = arr[p2++];
  52. }
  53. for(int j=0; j<help.length; j++){
  54. arr[L+j] = help[j];
  55. }
  56. return sum;
  57. }
  58. public static void main(String[] args) {
  59. int[] arr = {3,3,2,6,1,9,4,7,11,8,10,5};
  60. System.out.println(smallSum(arr));
  61. for(int num : arr){
  62. System.out.print(num + " ");
  63. }
  64. }
  65. }

 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号