我看到已经有任何公认的答案,但我认为在这种情况下,使用for
具有适当索引变量的循环将比for
适用于数组和集合的循环更方便。例如,看看随着时间的推移会发生什么。 a2
总是相同的:[4 5 6 7 8]
,并且应该插入的元素的索引a1
是0, 1, 2, 3, 4
。现在,第一个元素 ( 4
) 应该插入到a1
at 位置1
。之后,5
需要在 position 插入下一个元素 ( ) 3
。然后6
需要在位置插入5
。一般情况下,i
第一个元素a2
需要插入i*2+1
到a1
. 这将一直保持到i*2+1
大于 中的元素数量a1
,或者您用完 中的元素a2
。考虑到这一点,在所有较早的元素都已插入之后,插入 的第一个元素的正确索引是,i
因为添加 at只是将一个元素添加到列表的末尾。a2
a1
Math.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
s,因为这是所有代码所依赖的,尽管随机访问 withget
只会在有效支持它的列表上有效(例如,它对ArrayList
s 很好,但对链表表现不佳)。这些只是列表的事实也表明您可以考虑使用ListIterator
s的解决方案。
在上下文中,并使用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;
}