如何删除数组中相等的元素?

4

在Java代码中使用ArrayUtils,可以从Java数组中删除一个元素。下面的代码将删除特定索引处的一个元素(在代码中为“2”),该元素的值等于“10”。

import java.util.Arrays;

import org.apache.commons.lang3.ArrayUtils;


public class RemoveObjectFromArray{

 public static void main(String args[]) {


     int[] test = new int[] { 10, 13, 10, 10, 105};

     System.out.println("Original Array : size : " + test.length );
     System.out.println("Contents : " + Arrays.toString(test));

     //let's remove or delete an element from Array using Apache Commons ArrayUtils
     test = ArrayUtils.remove(test, 2); //removing element at index 2

     //Size of array must be 1 less than original array after deleting an element
     System.out.println("Size of array after removing an element  : " + test.length);
     System.out.println("Content of Array after removing an object : "
                       + Arrays.toString(test));

 } }

它的输出结果如下:

run:
Original Array : size : 5
Contents : [10, 13, 10, 10, 105]
Size of array after removing an element  : 4
Content of Array after removing an object : [10, 13, 10, 105]

如何修改代码以获得以下输出:
run:
Original Array : size : 5
Contents : [10, 13, 10, 10, 105]
Size of array after removing an element  : 2
Content of Array after removing an object : [ 13, 105]

2
你确定不想使用Set(然后再将其转换回数组)吗? - TheLostMind
1
@user3678356 - 使用集合可能是你最后的选择,不幸的是它也是最简单的选择 :) - TheLostMind
代码中显示的数组是虚拟的。我必须处理具有成千上万个元素的数组,多次使用函数是不切实际的。我正在寻找类似于以下内容的东西。如果([i]==10) {ArrayUtils.remove([i])}; - Soon
@CommuSoft 我的意思是,无论这个问题使用了什么库/数据结构,解决方案都不会比O(n)更快。所谓“更简单”的只是代码行数而已。实际上,new Set()ArrayUtils内部也是迭代/循环数组进行操作的。如果我们必须要循环数组,为什么不在循环过程中完成工作并避免添加额外开销? c * n + k也是 O(n),但它比 n 更慢。其中的 k 是指 hashfunc。请注意,我们可以认为 hashfunc 的时间复杂度为 O(1),而不是 O(n) - Kent
你自己实现一个列表,让 add() 方法检查值是否已经在列表中不是更容易吗?当然,根据你想要存储的内容,你可能需要重写 hashCode() 和 equals() 方法,但是你可以将其用于任何事情。 - Greg
显示剩余6条评论
5个回答

3
尝试使用这段代码。
while (ArrayUtils.contains(test, 10))  {
  //let's remove or delete an element from Array using Apache Commons ArrayUtils
  test = ArrayUtils.removeElement(test, 10); //removing element with value 10
}

它应该可以解决你的问题。

2
这只能解决特定的情况,我猜 OP 希望它适用于任何数组。 - Ceiling Gecko
1
不是一个高效的解决方案。原始问题将不得不遍历整个数组。同时,删除和移动数组中的元素也需要一些时间。 - TheLostMind

2
我建议您在这种情况下使用ArrayList,但如果您想继续使用数组,可以按照以下步骤操作:
int count = 0;
for(int i = 0; i < test.length; i++){
  if (test[i] == 10) {
    count++;
  }
 }
 int[] newTest = new int[count];
 count = 0;
 for( int = 0; i < test.length; i++){
   if(test[i] != 10){
     newTest[count++] = test[i];
   }
  }

我没有测试过它


2

虽然不是一种优雅的方法,但如果您只想使用数组,可以使用以下代码:

public static void removeDupes(int[] array) {

    int[] forbiddenNumbers = new int[array.length];

    Arrays.sort(array);

    for(int number : array) {
        if(ArrayUtils.contains(forbiddenNumbers, number){
            int index = Arrays.binarySearch(array, number);
            while(index >= 0) {
                ArrayUtils.remove(array, index);
                index = Arrays.binarySearch(array, number);
            }
            ArrayUtils.remove(forbiddenNumbers, Arrays.binarySearch(forbiddenNumbers, number);
        } else {
            ArrayUtils.add(forbiddenNumbers, number);
        }
    }
}

这应该适用于数组中存在的任何重复项。

它的作用是遍历数组,在另一个数组中保存所有唯一的数字,一旦在数组中遇到重复项,则从原始数组中删除该数字的所有实例,然后从唯一数字数组中删除该数字,因为它不再存在于原始数组中。

这是一个非常费力的解决方案,你应该认真考虑使用其他方法(例如使用集合),但如果你想纯粹使用数组来完成,则这个方法可以起作用。


2

这个方法只需要一个循环,而不会增加其他库或数据结构的开销,时间复杂度为O(n)

        int[] test = new int[] { 10, 13, 10, 10, 105};
        int tobeDel = 10;
        int[] tmp = new int[test.length];
        int j=0;
        for (int i=0;i<test.length;i++) {
            if (test[i] == tobeDel) {
                continue;
            }    
            tmp[j] = test[i];
            j++;
        }
        int[] result = new int[j];
        System.arraycopy(tmp, 0, result, 0, j);

如果您编写自己的方法,请返回result


1

解决方案1

我没有找到满足您需求的单一函数,但是这段代码可以实现。

while(ArrayUtils.removeElement(test,10).length!=test.length)
    test=ArrayUtils.removeElement(test,10);

你可以使用 removeElement,它将删除该元素并返回新的数组。如果没有要删除的元素,则会返回相同的列表。

解决方案2

这个方法也能实现相同的效果,但不需要进行任何迭代。如果这正是你所寻找的。

Arrays.sort(test);
int[] finalValue =ArrayUtils.subarray(test, 0, ArrayUtils.indexOf(test,10));
ArrayUtils.addAll(finalValue,ArrayUtils.subarray(test,ArrayUtils.lastIndexOf(test,10), test.length));

这会对数组进行排序,并从开头到第一次出现的位置,以及从最后一次出现的位置到数组末尾进行切割。

最坏时间复杂度O(n^2)? (解决方案1) - Kent
@Kent 是的,但它可以简化,我只是给了他逻辑。必须修改以使其更好。毕竟我不是在做他的家庭作业。;-) - Dileep
在我看来,n*n的解法可能是这个问题最慢的解法。另外,解法2将O(n)变成了O(nlogn),也并非必须。而且,它改变了其余元素的顺序。好吧,或许对于原帖作者来说性能不是一个问题...这是我的意见。 - Kent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接