简体   繁体   中英

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.

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. Any help with me understanding the differences in these solutions would be greatly appreciated! Thanks!

Example code with two methods - merge and 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. 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.

Your method doesn't modify the rankings parameter, instead it creates a new int array (result), and you work on it. Try directly set value on the rankings array, not on result array, or simply set the result variable to the rankings.

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. Use instead System.arrayCopy which copies into an EXISTING array:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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