0

作业:寻找更好的策略或方法而不是完整的代码。

在两种情况下,我有两个整数数组列表:

  1. 第一个列表大于第二个
  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

几点评论:

  • 我可能会返回一个新列表,而不是任意修改其中一个
  • 新算法则更简单:
    • 创建一个新的空列表
    • 在计数器上循环从 0 到两个列表大小的最小值并交错
    • 完成后,检查其中一个列表是否有更多项目并添加它们(例如使用addAlland的组合subList
    • 返回列表
  • 如果您不需要改变两个原始列表,您可以用更短的方式声明它们: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 个列表的方式。

首先,要认识到这里要解决的困难部分是迭代,而不是创建新列表。从一个可迭代对象创建一个新列表是微不足道的。

所以想象我们有一个这样的方法:

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>循环遍历每个迭代器。这是队列 (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()),则将其放到队列的后面。

这对于任何数量的列表都完全相同,并且不需要任何 icky 条件检查。

要使用它创建一个新列表,您可以这样做:

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

我建议以下代码:

private static List<Integer> joinTwoLists(List<Integer> a, List<Integer> b) {
    final boolean aIsBigger = a.size() > b.size();
    final List<Integer> joined = new ArrayList<>(aIsBigger ? a : b);
    final AtomicInteger index = new AtomicInteger(1);
    for (Integer value : aIsBigger ? b : a) {
        joined.add(index.getAndAdd(2), value);
    }
    return joined;
}
于 2018-08-24T22:53:35.553 回答
0

这是我的方法。

public static void interleave(ArrayList<Integer> a1, ArrayList<Integer> a2) {
    int start = 0;
    int i;
    int size = a1.size();
    for (i = 1; i < a1.size(); i += 2) {
        if (start < a2.size()) {
            a1.add(i, a2.get(start++));
        }
    }
    while (a1.size() < (size + a2.size())) {
        a1.add(i++, a2.get(start++));
    }

}
于 2020-02-21T19:45:56.890 回答