从没有孔的阵列中删除

时间:2014-05-05 13:49:44

标签: java arrays

我有Array CarCar个包含arrayList个对象,而且我已经卡住了一段时间来获取车号并需要删除所有对象的方法有那个车号然后返回该阵列没有任何漏洞。这是我的作业所以我不能使用任何Array.IndexOutOfBounds方法。

我已尝试执行以下操作但由于某些原因,当我尝试运行它时,它不会编译并给我toString错误并引用我的noOfCars方法(它打印数组中的所有单元格。

public void removeCarNumbers(int CarNum) { int count = 0; for(int i = 0; i < this.noOfCars; i++) { if(this.cars[i].getCarNum() == CarNum) { this.cars[i] = this.cars[noOfCars- 1 - count]; count++; } } CarsLines [] newArr = new CarLines[this.noOfCars- count]; for(int i = 0; i< this.noOfCars - count; i++) { newArr[i] = this.cars[i]; } this.cars= newArr; } ,保存现在实际存在的汽车数量,因为我们使用容器构造函数构建数组,以便为​​将来的汽车保留更多的位置。

{{1}}

*编辑:玩了之后我仍然得到一个错误,引用我的toString()方法。它也有问题吗?     public String toString()     {         String output =“”;         for(int i = 0; i&lt; this.noOfCars; i ++)             output + =“”+ this.cars [i] .toString()+“\ n”;         返回输出;     }

4 个答案:

答案 0 :(得分:2)

尝试:

// count
int count = 0;
for(int i = 0 ; i < this.cars.length ; ++i) {
    if(this.cars[i].getCarNum() == CarNum) {
        ++count;
    }
}
// create new array
CarsLines[] newArr = new CarLines[this.cars.length - count];
int index = 0;
for(int i = 0 ; i < this.cars.length ; ++i) {
    if(this.cars[i].getCarNum() != CarNum) {
        newArr[index++] = this.cars[i];
    }
}
// assign
this.cars = newArr;

答案 1 :(得分:0)

我不认为这两个循环正在按照你的想法行事。在第一个循环中,您应该删除具有相同数字的Car,或者将它们设置为null

for (int i = 0; i < this.cars.length; i++) {
    if (this.cars[i] != null && this.cars[i].getCarNum() == CarNum) {
        this.cars[i] == null;
    } else {
        count++;
    }
}

现在这将消除重复,并保持唯一Car的计数。在第二个循环中,只填写非null值:

CarsLines [] newArr= new CarLines[count];
int index = 0;
for(int i = 0; i< this.cars,length; i++)
{
    if (this.cars[i] != null) { // Only pass in the non-null values
        newArr[index] = this.cars[i]; 
        index++;
    }
}
this.cars= newArr;

在你创建这个列表的同一副本之前,因为你是在一对一的基础上填写它,即相同的索引。

另一种可行的方法是实现转换:

for (int i = 0; i < this.cars.length; i++) {
    if (this.cars[i] != null && this.cars[i].getCarNum() == CarNum) {
        for (int j = i+1; j < this.cars.length; j++) { // This loop will shift the 
            this.cars[j-1] = this.cars[j];             // whole list down one when
        }                                              // a duplicate is found,
                                                       // overwriting it.
        i--;              // sets the index back to recheck the shifted list.
        this.noOfCars--;  // You removed one duplicate by overwriting it
    }
}

为了回应 @Boris The Spiders 评论,您可以通过消除内部for循环来降低此算法的复杂性。我建议通过跟踪最后一个有效位置并将其用于更新来完成此操作。

int writeIndex = 0;
for (int readIndex = 0; readIndex < this.cars.length; readIndex++) {
    if (this.cars[readIndex] != null && this.cars[readIndex].getCarNum() == CarNum) {
        // pass on this because nextIndex should track only the valid cars.
    } else {
        this.cars[writeIndex++] = this.cars[readIndex];
    }
    if (writeIndex < readIndex) {
        this.cars[i] = null;
    }
}

我们的想法是保留一个用于阅读的索引(i)和一个用于编写writeIndex的索引。如果您的readIndex超出writeIndex(这意味着您发现了重复内容),则应在阅读后将其清除,并且您将转移到之前的writeIndex

编辑为了回应您的问题,您应该特别注意计算noOfCars的方式,因为这可能是您Exception的来源,而是尝试使用数组中的内部length属性更可靠的索引方法:

public String toString() {
    String output = "";
    for (int i = 0; i < this.cars.length; i++) {
        if (this.cars[i] != null) {
            output += "" + this.cars[i].toString() + "\n";
        } else {
            // condition that the i-th car is null
            output += "null\n"; // one possible approach
            // you could also do nothing and your toString would output just the non-null cars
         }
    }
    return output;
}

为了确保可靠性,以效率为代价,您可以实施count()方法来仔细检查您的跟踪。也许作为临时检查,直到你确定它正常工作。

public int getNumCars() {
    int c = 0;
    for (int i = 0; i < this.cars.length; i++) {
        if (this.cars[i] != null) {
            c++;
        }
    }
    return c;
}

答案 2 :(得分:0)

对于您移除的每辆车,请尝试将阵列中的最后一个元素交换到“洞”中。 Keepa计数器用于有效的max元素,并在每次将元素换成hold时将其递减。您基本上是对阵列元素进行重新整理

int max=this.noOfCars.length; 
int i=0;
do{
        if(this.cars[i]==null)
            break; 
        if(this.cars[i].getCarNum() == CarNum) {
            this.cars[i] = this.cars[max-1];
            this.cars[max-1] = null;
        }
         else{
            i++;
         } 
   }while(1==1);

PS:您可能需要为边界条件添加一些检查(如空数组)

答案 3 :(得分:0)

这是一个简单的例子,说明如何使用单个循环,没有嵌套循环。

这个想法是你跟踪你可能删除的元素(你找到了多少null个元素)然后,如果不删除当前元素,只需将它移回去号。

public static void main(final String[] args) throws IOException {
    final Integer[] data = {1, 2, 2, 3, 4, 5, 1, 2, 3, 7, 8, 2, null, null, null};
    int shift = 0;
    for (int i = 0; i < data.length; ++i) {
        if (data[i] == null || data[i] == 2) {
            shift++;
            data[i] = null;
        } else if (shift > 0) {
            data[i - shift] = data[i];
            data[i] = null;
        }
    }
    System.out.println(Arrays.toString(data));
}

输出:

[1, 3, 4, 5, 1, 3, 7, 8, null, null, null, null, null, null, null]

因此,您可以看到2已被移除,其余已被移除。