Java Recursion - 数组中的逆序整数,它是如何工作的?

时间:2017-09-27 10:36:15

标签: java arrays recursion int reverse

  public static void reversePrint(int[] numbers){
     if(numbers.length == 0) //Base case
         return;  

     int[] a = new int[numbers.length-1];
     for(int i = 0; i < numbers.length-1;i++)
         a[i] = numbers[i+1];

     reversePrint(a);
     System.out.println(numbers[0]); 
  }

 public static void main(String[] args){

   int[] array = new int[]{5,1,34,12,7};
     reversePrint(array);
}


Output:
 7
 12
 34
 1
 5

一切都非常简单,有一个名为reversePrint的功能。当你将这些数字传递给函数reversePrint时,它会取出第一个值(在这种情况下&#39; 5&#39;)然后再次调用reversePrint,现在使用较小的列表。

这一直持续到最后我们没有更多的数字,并开始打印出来。

如果数字列表越来越少,每次删除第一个数字,我的混淆就在第10&#39;如何调用&#39; System.out.println(数字[ 0]);&#39;检索已从列表中删除的数字,并以相反的顺序执行此操作?

5 个答案:

答案 0 :(得分:2)

这是一个了解此递归中的调用堆栈的方案:

reversePrint([5,1,34,12,7]) {
   reversePrint([1,34,12,7]) { // <-- this list IS A COPY, it just ignores the first number
      reversePrint([34,12,7]) {
         reversePrint([12,7]) {
            reversePrint([7]) {
               reversePrint([]);
               print(7); // <-- this is the first number of the current list
            };
            print(12);
         };
         print(34);
      };
      print(1);
   };
   print(5);
};

如您所见,System.out.println(numbers[0])被称为AFTER传播递归。请注意,每次调用都会创建一个新数组,您不会丢失第一个数字。

答案 1 :(得分:1)

首先,您实际上并未移除数字:您将其从numbers复制到a,跳过位置0中的数字。 System.out.println打印numbers,因此索引0的整数仍然相同。

其次,System.out.println语句在递归调用之后,因此它将在该调用返回后执行。所以基本上,将执行的第一个System.out.println将是最后一次调用中的那个:{/ p>

for ...
reversePrint
|
|    for ...
|    reversePrint
|    |
|    |    for ...
|    |    reversePrint
|    |    |
|    |    |    for ...
|    |    |    reversePrint
|    |    |    |
|    |    |    |    for ...
|    |    |    |    reversePrint
|    |    |    |    |
|    |    |    |    |    return
|    |    |    |    |
|    |    |    |    System.out.println
|    |    |    |
|    |    |    System.out.println
|    |    |
|    |    System.out.println
|    |
|    System.out.println
|
System.out.println

答案 2 :(得分:0)

这是一个非常无效的

实现
Arrays.asList(5, 1, 34, 12, 7).reverse().forEach(System.out::println)

但是为了回答你的问题,reversePrint创建了一个新数组,第一个项目从数组中删除,然后打印出原始数据的第一个。第二个电话将收到[1,34,12,7],因为第一个电话已经删除了5,所以它将打印出1。

答案 3 :(得分:0)

  

如何调用'System.out.println(numbers [0]);'检索已从列表中删除的数字,并以相反的顺序执行此操作?

此代码中的任何数组都没有删除任何数字。每次递归调用都会创建一个新数组,并将当前数组的所有元素复制到第一个元素之外。

因此,传递给reversePrint()的第i个调用的数组包含原始数组的最后一个n-i + 1个元素。

当为空数组调用reversePrint()时,递归结束。当最后一次递归调用返回时,倒数第二个调用将打印numbers[0],其中包含原始数组的最后一个元素。然后前面的reversePrint()打印numbers[0],其中包含原始数组的最后一个元素,依此类推......

这些是递归调用:

reversePrint({5,1,34,12,7})
reversePrint({1,34,12,7})
reversePrint({34,12,7})
reversePrint({12,7})
reversePrint({7})
reversePrint({})

现在,在每个人都返回后,会打印numbers[0],所以你得到了

7
12
34
1
5

答案 4 :(得分:0)

也许这是经典的方式(而不是像你一样制作数组的副本),它会更清楚发生的事情。

// Private version to pass the offset which increases on each call.
private static void reversePrint(int[] numbers, int from){
    // Base case - stop at end of array.
    if(numbers.length > from) {
        // Print everything else first.
        reversePrint(numbers, from+1);
        // Then the one I am at.
        System.out.println(numbers[from]);
    }
}

public static void reversePrint(int[] numbers){
    reversePrint(numbers, 0);
}

public void test() throws Exception {
    System.out.println("Hello world!");
    int[] array = new int[]{5,1,34,12,7};
    reversePrint(array);
}