0

宿題: 完全なコードではなく、より良い戦略またはアプローチを探しています。

2 つの条件の下で、整数の 2 つの arrayLists を取得しました。

  1. 最初のリストが 2 番目のリストより大きい
  2. 2 番目のリストは最初のリストよりも大きい

私の目標は、両方の条件下で list2 の要素を list1 にインターリーブすることでした。これを行うメソッドを作成しましたが、もっと良いことができる気がします。

条件 1 の予想される結果を次に示します。list2 の要素が使い果たされた後、list1 の要素をそのままにしておくことに注意してください。

list1: [10, 20, 30, 40, 50, 60, 70]
list2: [4, 5, 6, 7]
Combined: [10, 4, 20, 5, 30, 6, 40, 7, 50, 60, 70]

条件 2 の予想される結果を次に示します。list2 にはさらに要素があるため、list1 が使い果たされた後、これらの要素を list1 に追加します。

list1: [10, 20, 30, 40]
list2: [4, 5, 6, 7, 8, 9, 10, 11]
Combined: [10, 4, 20, 5, 30, 6, 40, 7, 8, 9, 10, 11]

私のコードでは、if-else ステートメントを使用して両方の条件を処理しています。次に、反復子を使用して list2 の要素を調べ、それらを list1 に挿入します。

public static void main(String[] Args)
{
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    numbers.add(10);
    numbers.add(20);
    numbers.add(30);
    numbers.add(40);
    //numbers.add(50);
    //numbers.add(60);
    //numbers.add(70);

    ArrayList<Integer> numbers2 = new ArrayList<Integer>();

    numbers2.add(4);
    numbers2.add(5);
    numbers2.add(6);
    numbers2.add(7);
    numbers2.add(8);
    numbers2.add(9);
    numbers2.add(10);
    numbers2.add(11);

    System.out.println("list1: " + numbers);
    System.out.println("list2: " + numbers2);

    interleave(numbers, numbers2);

    System.out.println();
    System.out.println("Combined: " + numbers);
}

public static void interleave(ArrayList<Integer> list1, ArrayList<Integer> list2)
{
    //obtain an iterator for the collection
    Iterator<Integer> itr2 = list2.iterator();

    //loop counter
    int count = 1;

    //handle based on initial size of lists
    if(list1.size() >= list2.size())
    {
       //loop through the first array and add elements from list 2 after each element
       while(itr2.hasNext())
       {
           //insert elements from list2
           list1.add(count, itr2.next());

           //make sure elements are getting added at 1, 3, 5, 7, 9, etc
           count = count + 2;
       }
    }
    else if(list1.size() < list2.size())
    {
       //loop through the first array and add elements from list 2 after each element
       while(itr2.hasNext())
       {
           if(count <= list1.size())
           {
               //insert elements from list2
               list1.add(count, itr2.next());

               //make sure elements are getting added at 1, 3, 5, 7, 9, etc
               count = count + 2;
           }
           else
           {
               //fill in the remainder of the elements from list2 to list1
               list1.add(itr2.next());
           }
       }
    }
}
4

5 に答える 5

6

このソリューションが気に入りましたか?

public static void main(final String[] args) {
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    numbers.add(10); numbers.add(20); numbers.add(30); numbers.add(40);
    //numbers.add(50); numbers.add(60); numbers.add(70);

    ArrayList<Integer> numbers2 = new ArrayList<Integer>();
    numbers2.add(4); numbers2.add(5); numbers2.add(6); numbers2.add(7);
    numbers2.add(8); numbers2.add(9); numbers2.add(10); numbers2.add(11);

    System.out.println("list1: " + numbers);
    System.out.println("list2: " + numbers2);
    List<Integer> interleaved = interleave(numbers, numbers2);

    System.out.println("\nCombined: " + interleaved);
}

public static List<Integer> interleave(
    final List<Integer> list1,
    final List<Integer> list2
) {
    List<Integer> result
        = new ArrayList<Integer>(list1.size() + list2.size());

    Iterator<Integer> it1 = list1.iterator();
    Iterator<Integer> it2 = list2.iterator();
    while (it1.hasNext() || it2.hasNext()) {
        if (it1.hasNext()) {
            result.add(it1.next());
        }
        if (it2.hasNext()) {
            result.add(it2.next());
        }
    }
    return result;
}
于 2013-01-27T20:18:42.663 に答える
2

いくつかのコメント:

  • それらの1つを任意に変更するのではなく、おそらく新しいリストを返したでしょう
  • 新しいアルゴリズムはより単純です。
    • 新しい空のリストを作成する
    • 0 から 2 つのリストのサイズの最小値までのカウンターでループし、インターリーブします。
    • 完了したら、リストの 1 つにさらに項目があるかどうかを確認し、それらを追加します (たとえば、 と の組み合わせを使用addAll) subList
    • リストを返す
  • 元の 2 つのリストを変更する必要がない場合は、以下を使用してより短い方法で宣言できます。List<Integer> numbers = Arrays.asList(10, 20, 30, 40);- 固定サイズのリストが作成されるため、追加または削除できないことに注意してください。
  • 現在のコードでは、次のようなものを複製する代わりに、次のようにすることができList listSmall, listBig; if (list1.size() < list2.size()) { listSmall = list1; listBig = list2; } else { /* the opposite */}ますlistSmall
于 2013-01-27T20:13:22.690 に答える
1

これは、この問題について別の考え方で、3 つのリストに簡単に拡張できる方法です。

まず、ここで解決するのが難しいのは、新しいリストを作成することではなく、反復であることを認識してください。iterable から新しいリストを作成するのは簡単です。

したがって、次のようなメソッドがあると想像してください。

public <T> Iterable<T> interleave(Iterable<? extends T>... lists) {
    return new Iterable<T>() {
       @Override
       public Iterator<T> iterator() {
           return new InterleavingIterator<T>(lists);
       }
    };
}

作成する必要があるのは、Iterator<T>各反復子を 1 つずつ循環する です。これはキュー (fifo) にとって完璧な仕事です! イテレータは次のようになります。

class InterleavingIterator<T> implements Iterator<T> {

    private final Queue<Iterator<? extends T>> iterators = new LinkedList<>();

    public InterleavingIterator(Iterable<? extends T>> iteratables) {
        for ( Iterable<T> iterable : iterables ) {
           Iterator<T> iterator = iterable.iterator();
           if ( iterator.hasNext() ) {
              this.iterators.add(iterator);
           }
        }
    }

    public boolean hasNext() {
        return !iterators.isEmpty();
    }

    public T next() {
        Iterator<T> nextIterator = iterators.poll();
        T result = nextIterator.next();
        if ( nextIterator.hasNext() ) {
           iterators.add(nextIterator);
        }
        return result;
    }
}

つまり、次の要素が要求されるたびに、キューの先頭にあるイテレータがポップされ、結果next()が返され、イテレータにまだ要素 ( hasNext()) がある場合はキューの後ろに置かれます。

これは、任意の数のリストに対してまったく同じように機能し、面倒な条件チェックは必要ありません。

それを使用して新しいリストを作成するには、次のようにします。

List<Integer> combined = new ArrayList<Integer>(interleave(list1, list2));
于 2013-01-27T20:39:34.373 に答える