Java 向整数数组的开头添加元素

Java 向整数数组的开头添加元素,java,Java,处理addBefore方法,该方法将新元素添加到int数组的开头,然后使现有元素的索引增加1 这是尝试运行时控制台中显示的内容- java.lang.RuntimeException:索引1应具有值11,但具有0 在IntArrayListTest.main IntArrayListTest.java:67 下面是我到目前为止的代码 public class IntArrayList { private int[] a; private int length; private int inde

处理addBefore方法,该方法将新元素添加到int数组的开头,然后使现有元素的索引增加1

这是尝试运行时控制台中显示的内容- java.lang.RuntimeException:索引1应具有值11,但具有0 在IntArrayListTest.main IntArrayListTest.java:67

下面是我到目前为止的代码

public class IntArrayList {
private int[] a; 
private int length;
private int index;
private int count;

public IntArrayList() {
    length = 0; 



    a = new int[4]; 

}

public int get(int i) { 

    if (i < 0 || i >= length) {
        throw new ArrayIndexOutOfBoundsException(i);
    }
    return a[i];
}
public int size() { 

    return length; 
}

public void set(int i, int x) {

    if (i < 0 || i >= a.length) {
        throw new ArrayIndexOutOfBoundsException(i);
    }
    a[i] = x;
}
public void add(int x) {

    if (length >= a.length) {

        int[] b = new int[a.length * 2];

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

        a = b;

        //count += 1;
    }

    a[length] = x;
    count++;

    length = length + 1;
}
public void addBefore(int x) {
    int[] b = new int[a.length*2];
    for (int i = 0; i < a.length; i++) {
        b[i+a.length] = a[i];
    }
    a = b;
    a[index] = x;
    length ++;
    }   
}

您可以使用Colt库中现有的Java方法。下面是一个使用Python语法使示例代码变小的小示例(我使用Jython):

from cern.colt.list import IntArrayList
a=IntArrayList()
a.add(1); a.add(2)    # add two integer numbers
print "size=",a.size(),a
a.beforeInsert(0, 10) # add 10 before index 0 
print "size=",a.size(),a
您可以使用该程序运行此代码。上述代码的输出为:

size= 2 [1, 2]
size= 3 [10, 1, 2]
如您所见,在1之前插入10,并增大大小 您可以随意将编码更改为Java,即将此类作为

import cern.colt.list.IntArrayList
IntArrayList a= new IntArrayList()

您可以改用ArrayList,然后将其转换为整数[]数组,这样可以简化代码。下面是一个例子: 首先创建ArrayList:

ArrayList<Integer> myNums = new ArrayList<Integer>();
接下来,我们可以使用ArrayList.toArray方法将ArrayList转换为整数数组。下面是一个例子:

Integer[] integerHolder = new Integer[myNums.size()];
Integer[] numsArray = (Integer[])myNums.toArray(integerHolder);
System.out.println(Arrays.toString(numsArray));
首先,我们创建一个与ArrayList大小相同的ArrayHolder,然后创建一个存储ArrayList元素的数组。我们将myNums.toArray强制转换为整数数组。结果如下。数字1将位于索引0处,其余元素将增加1个索引:

[1, 2, 3, 4, 5]

您可以在addBefore方法中完成整个过程,方法是将数组转换为该方法中的ArrayList,并在将其转换回数组之前将int x添加到ArrayList的0索引中。由于ArrayList只能接受包装类对象,因此只需将int基元数组转换为Integer类型即可,但它简化了addBefore方法

无论是添加第一个还是最后一个,如果阵列已满,则只需增加阵列大小

count字段似乎与length完全相同,而index作为一个字段似乎没有使用,也没有意义,所以将它们都删除

要重新排列数组中的值,请使用以下方法:

然后,两个添加方法应为:

public class IntArrayList {
    private int[] a; // Underlying array
    private int length; // Number of added elements in a

    // other code

    public void add(int x) {
        if (length == a.length) {
            int[] b = new int[a.length * 2];
            System.arraycopy(a, 0, b, 0, length);
            a = b;
        }
        a[length++] = x;
    }

    public void addBefore(int x) {
        if (length < a.length) {
            System.arraycopy(a, 0, a, 1, length);
        } else {
            int[] b = new int[a.length * 2];
            System.arraycopy(a, 0, b, 1, length);
            a = b;
        }
        a[0] = x;
        length++;
    }
}

如果答案要求您自己进行循环,那么类似的方法应该可以很好地实现这一点,但仍在继续:


我注意到这开始运行速度测试-不确定这样的测试有多有用,因为它基于cpu性能,而不是测试算法的复杂性。

您的解决方案有三个问题:

每次调用该方法时,都会增加的长度。这将快速创建OutOfMemoryException

当您将值从a复制到b时,您执行了b[i+a.length]=a[i];这意味着值将被复制到b的中间,而不是只移动一个位置

最后,将新值放在数组的末尾而不是开头

我之所以能够看到这些,是因为我在您的代码上使用了调试器。如果希望能够检测和修复代码中的问题,就需要开始使用此工具

所以固定解决方案可以做到这一点:

检查a是否已满,就像使用add方法完成一样,如果已满,则创建b,并将所有内容复制到它,依此类推

将所有值向前移动一个位置。最简单的方法是从长度向后循环到0

在数组的开头指定新值

以下是一个可行的解决方案:

public void addBefore(int x) {

    // increase length if a is full
    if (length >= a.length) {
        int[] b = new int[a.length * 2];
        for (int i = 0; i < a.length; i++) {
            b[i] = a[i];
        }
        a = b;
    }
    // shift all values one cell ahead
    for (int i = length; i > 0; i--) {
        a[i] = a[i-1];
    }

    // add new value as first cell 
    a[0] = x;
    length ++;
    }   
}

问题是什么?为什么每次添加之前都要将数组的大小增加一倍,为什么是b[i+a.length]?仅供参考,这对于数组来说是一个糟糕的操作。您可以通过使其循环来优化它,但链表更适合在开始添加。目标是在添加前及时执行n add&n adds。我的老师解释说,将数组加倍是最简单的方法,i+a.length是将数组中已有的元素复制到末尾,然后您可以轻松地在开始时添加新元素。当然,您需要增加大小,但仅当数组已满时,不是每次都这样。使用JUnit或TestNG之类的单元测试框架来测试您的类。写原子测试,一个测试测试一件事。这样,你就可以很容易地缩小问题的范围。我很确定整个想法是为了学习而手动创建一个由数组支持的列表,而不是最简单的解决方案。是的,事实上这是非常正确的,这是一个介绍级别,所以他们正在尝试建立基础概念。我尝试了这个,我得到了与我以前尝试过的相同的运行时间,控制台打印输出有点好笑,但是你花了41250毫秒,这似乎太长了在开始时添加一个值需要将数组中当前的所有元素向上移动1以适应新的值,您无法摆脱这一限制 t、 哪一个仍然是一个关于复杂性的问题?
public class IntArrayList {
    private int[] a; // Underlying array
    private int length; // Number of added elements in a

    // other code

    public void add(int x) {
        if (length == a.length) {
            int[] b = new int[a.length * 2];
            System.arraycopy(a, 0, b, 0, length);
            a = b;
        }
        a[length++] = x;
    }

    public void addBefore(int x) {
        if (length < a.length) {
            System.arraycopy(a, 0, a, 1, length);
        } else {
            int[] b = new int[a.length * 2];
            System.arraycopy(a, 0, b, 1, length);
            a = b;
        }
        a[0] = x;
        length++;
    }
}
public void addBefore(int x) {
        if(length + 1 >= a.length){
            int[] b = new int[a.length*2];
            b[0] = x;
            for (int i = 0; i < length; i++) {
                b[i + 1] = a[i];
            }
            a = b;
        } else {
            for (int i = length; i >= 0 ; i--) {
                a[i + 1] = a[i];
            }
            a[0] = x;
        }
        length++;
    }
public void addBefore(int x) {

    // increase length if a is full
    if (length >= a.length) {
        int[] b = new int[a.length * 2];
        for (int i = 0; i < a.length; i++) {
            b[i] = a[i];
        }
        a = b;
    }
    // shift all values one cell ahead
    for (int i = length; i > 0; i--) {
        a[i] = a[i-1];
    }

    // add new value as first cell 
    a[0] = x;
    length ++;
    }   
}