0

これを実行するのに問題があります。今までのやり方が正しいかどうかはわかりません。どこで範囲外エラーが発生しているのかよくわかりません。

手順は次のとおりです。

整数 a1 と a2 の 2 つの ArrayList をパラメーターとして受け取り、a2 の要素を交互のインデックスで a1 に挿入する interleave と呼ばれるメソッドを作成します。リストの長さが等しくない場合、長いリストの残りの要素は 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 に追加されるたびに、リストの大部分を 1 位置ずつシフトする必要があります。「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に挿入する必要があります。その後、次の要素 ( ) を位置 に挿入する必要があります。次に、位置に挿入する必要があります。一般に、 の番目の要素は の位置に挿入する必要があります。a115365ia2i*2+1a1. i*2+1これは、 の要素数よりも大きくなるか、 の要素がなくなるまで保持さa1a2ます。これを考慮すると、以前のすべての要素が挿入された後、 のi番目の要素をにa2挿入する適切なインデックスは です。これは、 atを追加するとリストの最後に要素が追加されるだけだからです。a1Math.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、残りの要素を一度に追加する方が理にかなっています。Listコードが依存するのgetはこれだけなので、私はこれを s を取るように書きましたArrayList。 )。これらが単なるリストであるという事実は、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挿入が行われるため、反復および挿入コードの一部が少しきれいになります。また、複雑なインデックス演算も必要ありません。を使用する実装を次に示します。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 に答える