代码之家  ›  专栏  ›  技术社区  ›  Manuel Selva

如何旋转列表中的非连续元素

  •  2
  • Manuel Selva  · 技术社区  · 14 年前

    我有一个列表,其中包含根据索引访问的元素。在这个列表中,我需要能够根据4个元素的索引“旋转”它们的组。例如,在列表中

    [a, b, c, d, e ,f , g, h, i, j, k, l]
    

    我想旋转c,f,i,l,以便

    [a, b, l, d, e ,c , g, h, f, j, k, i]
    

    你将如何实现这一点?

    2 回复  |  直到 14 年前
        1
  •  6
  •   Community miroxlav    7 年前

    一个简单的解决方案

    如果只需要在a的4个索引处旋转元素 List ,您只需编写这样一个简单的通用方法:

    static <T> void rotate4(List<T> list, int i0, int i1, int i2, int i3) {
        T item = list.get(i3);
        item = list.set(i0, item);
        item = list.set(i1, item);
        item = list.set(i2, item);
        item = list.set(i3, item);
    }
    

    这将循环旋转任意 List<T> . 记住 List.set 返回以前在该索引处的元素,因此 能够 如果需要,请将整个方法写在一行中:

        // one-liner version
        list.set(i3, list.set(i2, list.set(i1, list.set(i0, list.get(i3)))));
    

    使用此助手方法,您将拥有:

        List<Character> list = Arrays.asList(
            'a','b','c','d','e','f','g','h','i','j','k','l'
        );
    
        System.out.println(list);
        // [a, b, c, d, e, f, g, h, i, j, k, l]
        //        *        *        *        *
    
        rotate4(list, 2, 5, 8, 11);
    
        System.out.println(list);       
        // [a, b, l, d, e, c, g, h, f, j, k, i]
        //        *        *        *        *
    

    更通用的解决方案

    如果 您需要一种方法来为任意距离旋转任意数量的元素,然后您可以创建 现场视图 另一个 ,然后你可以 Collections.rotate 那个观点。

    如果 元素是连续的,例如,您只需使用 subList :

        List<Character> list = Arrays.asList(
            'a','b','c','d','e','f','g','h','i','j','k','l'
        );
    
        System.out.println(list);
        // [a, b, c, d, e, f, g, h, i, j, k, l]
        //     *  *  *  *  *
    
        System.out.println(list.subList(1, 6));
        // [b, c, d, e, f]
    
        Collections.rotate(list.subList(1, 6), -2);
        System.out.println(list);
        // [a, d, e, f, b, c, g, h, i, j, k, l]
        //     *  *  *  *  *
    

    由于元素不是连续的,因此不能使用 子列表 但是你可以写例如 PeriodicalLiveViewList 班级。你希望能够写这样的东西:

        System.out.println(PeriodicalLiveViewList.of(list, 3, 2));
        // [c, f, i, l]
    
        Collections.rotate(PeriodicalLiveViewList.of(list, 3, 2), 1);
    

    基本上你创造了另一个 其元素是另一个元素的每三个元素 ,从索引2开始,作为 现场视图 .

    如果你用的是番石榴,有 ForwardingList 你可以建立在上面。您可以实现 decorator pattern 如果有必要,也可以从头开始。

    相关问题

        2
  •  2
  •   mlschechter    14 年前

    这就是我想到的。这是一个相当简单的蛮力解决方案,但它是可扩展的。

    import java.util.Arrays;
    import java.util.List;
    
    public class ArrayRotator {
    
        public static void main(String... args) {
            List<String> target = Arrays.asList("a", "b", "c", "d", "e", "f", "g",
                    "h", "i", "j", "k", "l");
            System.out.println(target);
            target = rotate(target, 3);
            System.out.println(target);
        }
    
        private static List<String> rotate(List<String> aList, int anOffset) {
            String[] result = new String[aList.size()];
            for (int i = 0; i < aList.size(); i++) {
                if (0 == (i + 1) % anOffset) {
                    if (aList.size() > (i + anOffset)) {
                        result[i + anOffset ] = aList.get(i);
                    } else {
                        result[anOffset - 1] = aList.get(i);
                    }
                } else {
                    result[i] = aList.get(i);
                }
            }
            return Arrays.asList(result);
        }
    }
    

    我得到的结果是:

    [a, b, c, d, e, f, g, h, i, j, k, l]
    [a, b, l, d, e, c, g, h, f, j, k, i]
    

    我没想到 Collections 在这种情况下,它的功能似乎比这要复杂一些。我不确定哪种算法在大列表上更有效。也许您可以将以下功能结合起来:

    import java.util.List;
    
    public class ListRotator {
    
        public static void main(String... args) {
            List<String> target = Arrays.asList("a", "b", "c", "d", "e", "f", "g",
                    "h", "i", "j", "k", "l");
            System.out.println(target);
            rotate(target, 3);
            System.out.println(target);
        }
    
        private static void rotate(List<String> aList, int anOffset) {
            for (int i = anOffset-1; i < aList.size()-anOffset; i += anOffset) {
                Collections.rotate(aList.subList(i, i+anOffset), -1);
            }
            Collections.rotate(aList.subList(anOffset-1, aList.size()), 1);
        }
    
    }
    

    它生成与上面相同的输出。