Java:将多个数组交错到单个数组中

Java:将多个数组交错到单个数组中,java,arraylist,Java,Arraylist,我发现了将两个ArrayList交织成一个的问题,但这是用PHP实现的。我在采访中也被问到了这个问题,但解决不了,回来看是否已经解决了,但我只能找到这个 有指向伪代码或方法定义的指针吗 大(O)限制:O(n)-时间成本和O(1)-空间成本 示例: a[]=a1,a2,…,an b[]=b1,b2,…,bn 将阵列列表重新排列为a1、b1、a2、b2、…、an、bn Editv1.0:数组列表a[]和b[]的大小相同 Editv2.0:如果问题扩展到在给定的两个数组中的一个数组中重新排列,但不创建

我发现了将两个ArrayList交织成一个的问题,但这是用PHP实现的。我在采访中也被问到了这个问题,但解决不了,回来看是否已经解决了,但我只能找到这个

有指向伪代码或方法定义的指针吗

大(O)限制:O(n)-时间成本和O(1)-空间成本

示例:
a[]=a1,a2,…,an
b[]=b1,b2,…,bn
将阵列列表重新排列为a1、b1、a2、b2、…、an、bn

Editv1.0:数组列表a[]和b[]的大小相同


Editv2.0:如果问题扩展到在给定的两个数组中的一个数组中重新排列,但不创建新数组,该怎么办?

为简单起见,假设两个数组的长度相同,并且是
int
数组

int[] merge(int[] a, int[] b)
{
    assert (a.length == b.length);

    int[] result = new int[a.length + b.length];

    for (int i=0; i<a.length; i++)
    {
        result[i*2] = a[i];
        result[i*2+1] = b[i];
    }

    return result;
}
int[]合并(int[]a,int[]b)
{
断言(a.length==b.length);
int[]结果=新int[a.length+b.length];
对于(int i=0;i我相信Matt答案中的mod(%)运算是不正确的。在相同的假设下(即数组长度相同),我会提出以下解决方案:

static int[] merge(final int[] a, final int[] b)
{
    final int[] result = new int[a.length * 2];

    for (int i=0; i < a.length; i++)
    {
        result[i << 1] = a[i];
        result[(i << 1) + 1] = b[i];
    }

    return result;
}
静态int[]合并(最终int[]a,最终int[]b)
{
最终整数[]结果=新整数[a.length*2];
for(int i=0;i结果[i我认为对于数组或基于数组的列表,在给定的约束(
O(n)
time和
O(1)
space,即没有额外的空间)下,这是不可行的。(当然,假设我们不能简单地创建一个新的列表对象来委托给原始对象。)

如果您有两个链表,这是可行的-如果我们假设垃圾收集器足够快,即从一个列表中删除一个元素并将其添加到另一个列表中不会违反空间限制

public <X> void interleaveLists(List<X> first, List<X> second)
{
    ListIterator<X> firstIt = first.listIterator();
    ListIterator<X> secondIt = second.listIterator();
    while(secondIt.hasNext()) {
        fistIt.next();
        firstIt.add(secondIt.next());
        secondIt.remove();
    }
}
公共无效交错列表(先列表,后列表)
{
ListIterator firstIt=first.ListIterator();
ListIterator secondIt=second.ListIterator();
while(secondIt.hasNext()){
fistIt.next();
firstIt.add(secondIt.next());
secondIt.remove();
}
}
此方法适用于任何一对列表,但对于链表仅为O(n)

对于可以修改指针的自定义链表,我们不必依赖垃圾收集器,只需更改节点即可。对于单链表:

public void interleaveLinkedLists(Node<X> firstList, Node<X> secondList) {
    while(secondList != null) {
        Node<X> nextFirst = firstList.next;
        Node<X> nextSecond = secondList.next;
        firstList.next = secondList;
        secondList.next = nextFirst;
        firstList = nextFirst;
        secondList = nextSecond;
    }
}
public void interleaveLinkedList(节点第一列表,节点第二列表){
while(secondList!=null){
节点nextFirst=firstList.next;
节点nextSecond=secondList.next;
firstList.next=secondList;
secondList.next=nextFirst;
firstList=nextFirst;
secondList=nextSecond;
}
}
对于双链接列表,我们还必须调整prev指针

第一段中提到的包装变体如下:

public List<X> interleaveLists(final List<X> first, final List<X> second)
{
   if (first.size() != second.size())
      throw new IllegalArgumentException();
   return new AbstractList<X>() {
      public int size() {
         return 2 * first.size();
      }
      public X get(int index) {
         return index % 2 == 0 ? first.get(index / 2) : second.get(index / 2);
      }
      // if necessary, add a similar set() method.  add/remove are not sensible here.
   };
}
公共列表交错列表(第一个最终列表,第二个最终列表)
{
if(first.size()!=second.size())
抛出新的IllegalArgumentException();
返回新的AbstractList(){
公共整数大小(){
返回2*first.size();
}
公共X获取(整数索引){
返回索引%2==0?first.get(index/2):second.get(index/2);
}
//如有必要,添加一个类似的set()方法。此处的add/remove不合理。
};
}

这实际上也是时间上的
O(1)

我已经完成了一个小的解决方案,假设您正在谈论使用
ArrayList
(请参阅我对问题的评论)。根据这里的一些回答,我可能过于简化了问题,但无论如何还是这样

下面的示例采用a和b类型的
ArrayList
,并通过在[0]之后插入b[0],在[1]之后插入b[1]等方式将它们交错。当然,这个片段天真地假设a和b的大小与您的Edit v1.0相同。它也不会按照Edit v2.0创建新的
ArrayList

//a and b are of type ArrayList<Integer>
for (int i = a.size(); i > 0; i--)
{
    a.add(i, b.get(i - 1));
}
//a和b属于ArrayList类型
对于(int i=a.size();i>0;i--)
{
a、 添加(i,b.get(i-1));
}

无论组合ArrayList时发生什么情况,列表的大小都将是ArrayList的两倍。

列表的大小不必相同:

public class InterleaveTwoLists<X> {

    public List<X> interleaveLists(final List<X> first, final List<X> second) {

        return new AbstractList<X>() {
            private int minSize;
            private int combinedMinSize;
            private int size;
            private List<X>largerList;
            {{
                minSize = Math.min(first.size(), second.size());
                combinedMinSize = minSize*2;
                size = first.size() + second.size();
                largerList = first.size() > minSize ? first : second;
            }}

            public int size() {
                return size;
            }

            public X get(int index) {
                if (index < combinedMinSize) {
                    return index % 2 == 0 
                        ? first.get(index / 2) 
                        : second.get(index / 2);
                }
                else { 
                    return largerList.get(index-minSize);
                }
            }
        };
    }
}
公共类交错列表{
公共列表交错列表(第一个最终列表,第二个最终列表){
返回新的AbstractList(){
私人机构;
私有int组合化;
私有整数大小;
私人名单;
{{
minSize=Math.min(first.size(),second.size());
combinedMinSize=minSize*2;
size=first.size()+second.size();
largerList=first.size()>minSize?first:second;
}}
公共整数大小(){
返回大小;
}
公共X获取(整数索引){
如果(索引
要测试这一点:

public class InterleaveTwoListsTest {

    private static final Logger log = 
        LoggerFactory.getLogger(InterleaveTwoListsTest.class);

    List<String> first = new ArrayList<String>() {
    { 
        add("one"); add("three"); add("five"); 
        add("seven"); add("eight"); add("nine");
    }};

    List<String> second = new ArrayList<String>() {
    { 
        add("two"); add("four"); add("six"); 
    }};


    private InterleaveTwoLists<String> interleaveTwoLists;

    @Before
    public void setUp() throws Exception {
        interleaveTwoLists = new InterleaveTwoLists<>();
    }

    @Test
    public void test() {
        List<String> combinedList = interleaveTwoLists.interleaveLists(first, second);
        for( int i = 0; i < first.size() + second.size(); i++) { 
            log.debug("{}: {}", i, combinedList.get(i));
        }
    }
}
公共类InterleaveTwoListTest{
专用静态最终记录器日志=
getLogger(interleaveTwoListTest.class);
List first=new ArrayList(){
{ 
添加(“一”);添加(“三”);添加(“五”);
添加(“七”);添加(“八”);添加(“九”);
}};
第二个列表=新的ArrayList(){
{ 
添加(“两”);添加(“四”);添加(“六”);
}};
私有交织列表;
@以前
public void setUp()引发异常{
InterleaveTwoList=新的InterleaveTwoList();
}
@试验
公开无效测试(){
List combinedList=interleavetwolits.interleavelist(第一、第二);
为了(
int[] merge(int[] a, int[] b) {
    return( IntStream.range( 0, a.length ).flatMap(
        n -> IntStream.of( a[n], b[n] ) ).toArray() );
}