简体   繁体   English

Java数组操作和递归

[英]Java Array Manipulation and Recursion

So I have spent a considerable amount of time struggling to comprehend what is wrong with my code. 因此,我花了很多时间努力理解代码的错误之处。 I have an example program that I compared mine to, which works. 我有一个示例程序,可以与我的示例进行比较。 My code is structured differently (it's all in one method, as requested by my professor) than the example (which uses two methods). 我的代码的结构(按照我的教授的要求,全部采用一种方法)与示例(使用两种方法)不同。 I'm supposed to create aa recursive, divide-and-conquer solution to count inversions in an int array. 我应该创建一个递归的分治解决方案来计算int数组中的反转。

I am lost on why the example program maintains the manipulations to the input array throughout the recursion, while mine does not. 我不知道为什么示例程序在整个递归中都维护对输入数组的操纵,而我的却没有。 I know Java is pass-by-value, so I am confused why the example works. 我知道Java是按值传递的,所以我很困惑为什么该示例有效。 Any help with me understanding the differences in these solutions would be greatly appreciated! 我的任何帮助,以了解这些解决方案之间的差异将不胜感激! Thanks! 谢谢!

Example code with two methods - merge and invCounter: 具有两种方法的示例代码-merge和invCounter:

public static long merge(int[] arr, int[] left, int[] right) {
  int i = 0, j = 0, count = 0;
  while (i < left.length || j < right.length) {
     if (i == left.length) {
        arr[i+j] = right[j];
        j++;
     } else if (j == right.length) {
        arr[i+j] = left[i];
        i++;
     } else if (left[i] <= right[j]) {
        arr[i+j] = left[i];
        i++;
     } else {
        arr[i+j] = right[j];
        count += left.length-i;
        j++;
     }
  }
  return count;
}

//the recursive function
public static long invCounter(int[] arr) {
  int sum = 0;

  if (arr.length < 2)
     return 0;

  int m = (arr.length + 1) / 2;
  int left[] = Arrays.copyOfRange(arr, 0, m);
  int right[] = Arrays.copyOfRange(arr, m, arr.length);
  sum += invCounter(left);
  sum += invCounter(right);
  sum += merge(arr, left, right);
  return sum;
}

My single-method implementation (attempt): 我的单方法实现(尝试):

public static int invCounter(int ranking[]) {
  int sum = 0;
  int result[] = new int[ranking.length];
  int resIndx = 0;

  if (ranking.length < 2) {
     return 0; //base case
  }

  //divide
  int left[] = Arrays.copyOfRange(ranking, 0, ranking.length/2);
  int right[] = Arrays.copyOfRange(ranking, ranking.length/2,                    
   ranking.length);
  sum += invCounter(left);
  sum += invCounter(right);

  int i = 0, j = 0;
  while (i < left.length || j < right.length) {
     if (i == left.length) {
        //i empty, just add j
        result[resIndx++] = right[j++];
     }
     else if (j == right.length) {
        //j empty, just add i
        result[resIndx++] = left[i++];
     }
     else if (right[j] < left[i]) {
        //inversion 
        result[resIndx++] = right[j++];
        sum += left.length - i;
     }
     else {
        //no inversion
        result[resIndx++] = left[i++];
     }
  }

  ranking = Arrays.copyOf(result, result.length);

  return sum;
}

Why is the example program able to maintain an updated array through the recursion while mine is not? 为什么示例程序能够通过递归维护更新的数组,而我的却不能呢?


UPDATE (10/22/15): So I discovered that I am able to get the correct results if I replace result with ranking and just modify this array directly. 更新(10/22/15):因此,我发现,如果将result替换为ranking并直接修改此数组ranking则能够获得正确的结果。 My question now though is why can't I use the result array to temporarily store the results and then copy them into the ranking (argument) array at the end? 我现在的问题是,为什么我不能使用结果数组临时存储结果,然后最后将它们复制到排名(参数)数组中? This seems to me like it would be doing the same exact thing as putting the values in earlier, however the changes to ranking aren't reflected if I change it at the end. 在我看来,这似乎和将值放在更早的位置完全相同,但是如果最后更改它, ranking的更改不会反映出来。

Your method doesn't modify the rankings parameter, instead it creates a new int array (result), and you work on it. 您的方法不会修改ranks参数,而是会创建一个新的int数组(结果),然后您可以对其进行处理。 Try directly set value on the rankings array, not on result array, or simply set the result variable to the rankings. 尝试直接在ranks数组上而不是在result数组上设置值,或者直接将result变量设置为ranks。

public static int invCounter(int ranking[]) {
  int sum = 0;
  int result[] = ranking;
//other code...

Edit: Or you can copy it's content, but not with Arrays.copyOf, because it first CREATES a new array and then copy into it. 编辑:或者,您可以复制它的内容,但不能复制Arrays.copyOf,因为它首先创建一个新数组,然后复制到其中。 Use instead System.arrayCopy which copies into an EXISTING array: 改用System.arrayCopy将其复制到现有数组中:

System.arrayCopy(result, 0, rankings, 0, result.length();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM