0

我无法让这个东西运行。我不确定到目前为止我所拥有的是否在正确的轨道上。我不太确定是哪里给了我一个越界错误。

以下是说明:

编写一个名为 interleave 的方法,该方法接受两个整数 a1 和 a2 的 ArrayLists 作为参数,并将 a2 的元素插入到 a1 中的交替索引处。如果列表长度不等,则较长列表的其余元素留在 a1 的末尾。比如a1存储[10,20,30],a2存储[4,5,6,7,8],interleave(a1,a2)的调用;应该将 a1 更改为存储 [10, 4, 20, 5, 30, 6, 7, 8]。如果 a1 存储了 [10, 20, 30, 40, 50] 而 a2 存储了 [6, 7, 8],则调用 interleave(a1, a2);将 a1 更改为存储 [10, 6, 20, 7, 30, 8, 40, 50]。

private static void interleave(ArrayList<Integer> a1,
        ArrayList<Integer> a2) {

    int i = a1.size();
    int j = a2.size();

    if (i < j) { // a1 is shorter than a2
        for (int k = 0; k < a1.size(); k++) { // before k passes a1 size
            a1.add(k+1, a2.get(k));
        }

        for (int l = a1.size(); l < a2.size(); l++) {
            a1.add(a1.size(), a2.get(l));
        }

    } else if (i > j) { // a1 is longer than a2
        for (int k = 1; k < a2.size(); k++) {
            a1.add(k+1, a2.get(k));
        }

    } else { // they are equal length
        for (int k = 1; k < a2.size(); k++) {
            a1.add(k+1, a2.get(k));
        }
    }
}
4

4 回答 4

3

这应该工作

private static void interleave(ArrayList<Integer> a1, ArrayList<Integer> a2) {
    int i = -1;
    for(Integer elem: a2) {
        if(i < a1.size()-1) {
            i += 2;
        } else {
            i += 1;
        }
        a1.add(i, elem);
    }
}

public static void main(String[] args) throws Exception {

    ArrayList<Integer> a1 = new ArrayList<>(Arrays.asList(10, 20, 30));
    ArrayList<Integer> a2 = new ArrayList<>(Arrays.asList(4, 5, 6, 7, 8));

    interleave(a1, a2);
    System.out.println(a1);
}

编辑:我不得不承认,这段代码实际上是一个非常糟糕的解决方案,因为对于长列表来说它会非常慢。每次将元素添加到 a1 时,列表的很大一部分都必须移动一个位置。因此,遵循“MadProgrammer”的建议,这是一种更好、更快的方法

private static void interleave(ArrayList<Integer> a1, ArrayList<Integer> a2) {
    ArrayList<Integer> r = new ArrayList<>(a1.size() + a2.size());

    for(int i = 0, j = 0; i < a1.size() || j < a2.size(); i++, j++) {
        if(i < a1.size()) r.add(a1.get(i));
        if(j < a2.size()) r.add(a2.get(j));
    }
    a1.clear();
    a1.addAll(r);
}
于 2013-10-09T00:33:12.647 回答
2

我看到已经有任何公认的答案,但我认为在这种情况下,使用for具有适当索引变量的循环将比for适用于数组和集合的循环更方便。例如,看看随着时间的推移会发生什么。 a2总是相同的:[4 5 6 7 8],并且应该插入的元素的索引a10, 1, 2, 3, 4。现在,第一个元素 ( 4) 应该插入到a1at 位置1。之后,5需要在 position 插入下一个元素 ( ) 3。然后6需要在位置插入5。一般情况下,i第一个元素a2需要插入i*2+1a1. 这将一直保持到i*2+1大于 中的元素数量a1,或者您用完 中的元素a2。考虑到这一点,在所有较早的元素都已插入之后,插入 的第一个元素的正确索引是,i因为添加 at只是将一个元素添加到列表的末尾。a2a1Math.min( i*2+1, l1.size() )l1.size()

我同意关于不放弃作业答案的评论,但由于已经有一个完整实现的答案,并且我想将 与循环for的索引进行对比,因此我将在此处包含代码。for-each更新的interleave方法是

public static <T> List<T> interleave( final List<T> l1, final List<T> l2 ) {
    for ( int i = 0; i < l2.size(); i++ ) {
        l1.add( Math.min( i*2+1, l1.size()), l2.get( i ));
    }
    return l1;
}

不过,这不一定是最有效的实现。for当您到达末尾l1并简单地一次添加剩余的元素时,完成循环会更有意义。我还写了这个来接受Lists,因为这是所有代码所依赖的,尽管随机访问 withget只会在有效支持它的列表上有效(例如,它对ArrayLists 很好,但对链表表现不佳)。这些只是列表的事实也表明您可以考虑使用ListIterators的解决方案。

在上下文中,并使用main演示它的方法:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Interleave {

    public static <T> List<T> interleave( final List<T> l1, final List<T> l2 ) {
        for ( int i = 0; i < l2.size(); i++ ) {
            l1.add( Math.min( i*2+1, l1.size()), l2.get( i ));
        }
        return l1;
    }

    public static void main(String[] args) {
        final List<Integer> l1 = new ArrayList<Integer>( Arrays.asList( 10, 20, 30 ) );
        final List<Integer> l2 = Arrays.asList( 4, 5, 6, 7 ,8 );
        System.out.println( interleave( l1, l2 ));
    }
}

再想一想之后,我认为ListIterator这里使用 a 有话要说。它使一些迭代和插入代码更清晰,特别是因为迭代光标ListIterator之前使用 a 插入。它也不需要任何复杂的索引算法。这是一个使用的实现:ListIterators

public static <T> List<T> interleaveWithIterators( final List<T> l1, final List<T> l2 ) {
    // Get an iterator for the l1, and position it after the first element
    // or at the end, if there's no first element.
    final ListIterator<T> it1 = l1.listIterator();
    if ( it1.hasNext() ) { it1.next(); } 

    // Get an iterator for l2.  While there are elements remaining in l2, 
    // keep adding them to l1 by calling it1.add().  While there are elements
    // in l1, this also requires pushing it1 forward by one element on each iteration.
    final ListIterator<T> it2 = l2.listIterator();
    while ( it2.hasNext() ) {
        it1.add( it2.next() );
        if ( it1.hasNext() ) { it1.next(); }
    }
    return l1;
}

为避免检查if ( it1.hasNext() ) { ... }每次迭代,您可以拆分 while 循环:

public static <T> List<T> interleaveWithIterators( final List<T> l1, final List<T> l2 ) {
    final ListIterator<T> it1 = l1.listIterator();
    if ( it1.hasNext() ) { it1.next(); } 
    final ListIterator<T> it2 = l2.listIterator();
    while ( it2.hasNext() && it1.hasNext() ) {
        it1.add( it2.next() );
        it1.next();
    }
    while ( it2.hasNext() ) {
        it1.add( it2.next() );
    }
    return l1;
}
于 2013-10-09T00:54:18.490 回答
0

这对我有用。

private static void interleave(ArrayList<Integer> 
a1, ArrayList<Integer> a2) {
int i = -1;
for(Integer elem: a2) {
    if(i < a1.size()-1) {
        i += 2;
    } else {
        i += 1;
    }
    a1.add(i, elem);
}
}

public static void main(String[] args) throws Exception {

ArrayList<Integer> a1 = new ArrayList<>(Arrays.asList(10, 20, 30));
ArrayList<Integer> a2 = new ArrayList<>(Arrays.asList(4, 5, 6, 7, 8));

interleave(a1, a2);
System.out.println(a1);
}
于 2014-01-29T08:51:55.657 回答
0
public static LinkedList<Integer> alternate(LinkedList<Integer> list1, LinkedList<Integer> list2){
    List<Integer> newList = new LinkedList<Integer>();
    Iterator<Integer> itr1 = list1.iterator();
    Iterator<Integer> itr2 = list2.iterator();
    while (itr1.hasNext() || itr2.hasNext()){
        if (itr1.hasNext()){
            newList.add(itr1.next());
        }
        if (itr2.hasNext()){
            newList.add(itr2.next());
        }
    }
    return newList;
}
于 2016-06-08T19:31:31.507 回答