在这篇博客中,我们将深入探讨如何使用Java解决一个有趣的问题:求解数组的小和问题。我们将首先理解问题的定义,然后逐步分析和解释给出的Java代码。
问题定义
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。例如,数组[1,3,4,2,5]的小和为1+1+3+1+1+3+2=12。
代码解析
首先,我们定义了一个类 Code02_SmallSum
,该类包含了一系列的方法,用于求解数组的小和。以下是我们将要讨论的主要方法:
smallSum方法
public static int smallSum(int[] arr) {if (arr == null || arr.length < 2) {return 0;}return process(arr, 0, arr.length - 1);
}
smallSum
方法是我们的主要方法,它接收一个整数数组作为输入,如果数组为空或者长度小于2,那么直接返回0,否则调用 process
方法进行处理。
process方法
public static int process(int[] arr, int l, int r) {if (l == r) {return 0;}// l < rint mid = l + ((r - l) >> 1);returnprocess(arr, l, mid)+process(arr, mid + 1, r)+merge(arr, l, mid, r);
}
process
方法是一个递归方法,它接收一个整数数组和两个索引 l
和 r
作为输入,表示要处理的数组范围。首先,如果 l
等于 r
,那么直接返回0。然后,计算中间索引 mid
,并递归地处理左半部分和右半部分,最后将两个部分合并。
merge方法
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;
}
merge
方法是用于合并两个部分的,它接收一个整数数组和三个索引 L
、 m
和 r
作为输入,表示要合并的数组范围和中间索引。这个方法的主要思想是使用两个指针 p1
和 p2
,分别指向左半部分的开始和右半部分的开始。然后,比较两个指针指向的元素,如果 p1
指向的元素小于 p2
指向的元素,那么将 p1
指向的元素加入到结果中,并向右移动 p1
,否则将 p2
指向的元素加入到结果中,并向右移动 p2
。这个过程一直持续到 p1
或 p2
到达各自的部分的末尾。
测试代码
// for testpublic static int comparator(int[] arr) {if (arr == null || arr.length < 2) {return 0;}int res = 0;for (int i = 1; i < arr.length; i++) {for (int j = 0; j < i; j++) {res += arr[j] < arr[i] ? arr[j] : 0;}}return res;}// for testpublic static int[] generateRandomArray(int maxSize, int maxValue) {int[] arr = new int[(int) ((maxSize + 1) * Math.random())];for (int i = 0; i < arr.length; i++) {arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());}return arr;}// for testpublic static int[] copyArray(int[] arr) {if (arr == null) {return null;}int[] res = new int[arr.length];for (int i = 0; i < arr.length; i++) {res[i] = arr[i];}return res;}// for testpublic static boolean isEqual(int[] arr1, int[] arr2) {if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {return false;}if (arr1 == null && arr2 == null) {return true;}if (arr1.length != arr2.length) {return false;}for (int i = 0; i < arr1.length; i++) {if (arr1[i] != arr2[i]) {return false;}}return true;}// for testpublic static void printArray(int[] arr) {if (arr == null) {return;}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}System.out.println();}// for testpublic static void main(String[] args) {int testTime = 500000;int maxSize = 100;int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {int[] arr1 = generateRandomArray(maxSize, maxValue);int[] arr2 = copyArray(arr1);if (smallSum(arr1) != comparator(arr2)) {succeed = false;printArray(arr1);printArray(arr2);break;}}System.out.println(succeed ? "Nice!" : "Fucking fucked!");}
在 main
方法中,我们生成了一些随机数组,并使用 smallSum
方法和一个简单的比较方法 comparator
进行了测试,以验证我们的解决方案是否正确。
总结
以上就是我们对求解数组的小和问题的Java代码的解析。希望这篇博客能够帮助你理解和掌握这个问题的解决方案。如果你有任何问题或者建议,欢迎在下面的评论区留言。