首页 > 解决方案 > 针对特定范围的元素递归地反转数组列表

问题描述

public static void reverse(ArrayList<Integer> numbers, int start, int end) {
    if (start < end) {
        int temp = numbers.get(start);
        numbers.set(numbers.indexOf(start), numbers.get(end));
        numbers.set(numbers.indexOf(end), temp);
        reverse(numbers, start + 1, end - 1);
    }
}

我正在尝试递归地反转数组列表中的元素。但是,示例输出如下:[1, 2, 3, 4]from 1-3return [4, 2, 2, 4]not:[1, 4, 3, 2]

标签: javarecursionarraylist

解决方案


tl;博士

你工作太辛苦了。无需编写递归reverse方法。

修改列表一部分的视图会影响原始列表。

Collections
.reverse(                                // Re-ordering a sublist view affects the original list.
    numbers                              // Your modifiable list of objects (Integer objects in your case). 
    .subList( 1 , 3 + 1 )                // Specify your desired subset that needs reversing, to get a view backed by the original list. Use zero-based index numbers. Add one as the ending is exclusive.
) ;

List::subList

调用的结果List::subList是直接基于原始列表的该部分的视图。如果更改原始列表,则更改子列表视图。

更重要的是,对于我们这里的目的,如果您更改子列表视图,您就会更改原始视图。因此,让我们仅反转子视图以影响原始视图。

当然,这只适用于可修改List的,例如ArrayList.

Collections.reverse

要反转列表,请调用实用程序方法Collections.reverse

在这两行代码中,我们制作了一个List,抓取该列表一部分的视图,反转该部分中的元素,从而影响原始列表。

List < Integer > numbers = new ArrayList <>( List.of( 1 , 2 , 3 , 4 ) );
Collections.reverse( numbers.subList( 1 , 3 + 1 ) ) ;

关于方法的两件事subList

  • 它令人讨厌地采用从零开始的索引号而不是序数的参数。
  • 它是半开的,意味着开始是包容的,而结束是排斥的。所以我们必须在我们想要包含的最后一个元素的索引中添加一个。

示例用法

再次尝试该代码,但添加调用以将列表转储到控制台。

List < Integer > numbers = new ArrayList <>( List.of( 1 , 2 , 3 , 4 ) );
System.out.println( "numbers = " + numbers );

Collections.reverse( numbers.subList( 1 , 3 + 1 ) ) ;
System.out.println( "numbers = " + numbers );

请参阅在 IdeOne.com 上实时运行的代码

数字 = [1, 2, 3, 4]

数字 = [1, 4, 3, 2]


推荐阅读