繁体   English   中英

如何使用Java中的辅助数组从列表中删除重复项?

[英]How to remove duplicates from a list using an auxiliary array in Java?

我试图通过创建一个临时数组来删除列表中的重复项,该数组存储重复项所在的索引,然后将原始数组复制到另一个临时数组中,同时将索引与我存储在第一个临时数组中的索引进行比较。

public void removeDuplicates()
{
    double tempa [] = new double [items.length];
    int counter = 0;
    for ( int i = 0; i< numItems ; i++)
    {
        for(int j = i + 1; j < numItems; j++)
        {
            if(items[i] ==items[j])
            {
                tempa[counter] = j;
                counter++;

            }
        }
    }

    double tempb [] = new double [ items.length];
    int counter2 = 0;
    int j =0;
    for(int i = 0; i < numItems; i++)
    {
        if(i != tempa[j])
        {
            tempb[counter2] = items[i];
            counter2++;

        }
        else
        {
            j++;

        }
    }

    items = tempb;
    numItems = counter2;
}

虽然逻辑看似正确,但我的编译器在给我一个arrayindexoutofbounds错误

tempa[counter] = j;

我不明白计数器如何增长到items.length的值以上,逻辑缺陷在哪里?

你为自己制造的东西很难。 让Java为您做繁重的工作。 例如,LinkedHashSet为您提供唯一性并保留插入顺序。 它比将每个值与每个其他值进行比较也更有效。

double [] input = {1,2,3,3,4,4};
Set<Double> tmp = new LinkedHashSet<Double>();
for (Double each : input) {
    tmp.add(each);
}
double [] output = new double[tmp.size()];
int i = 0;
for (Double each : tmp) {
    output[i++] = each;
}
System.out.println(Arrays.toString(output));

完成int数组,但很容易转换为double。

1)如果你不关心初始数组元素的顺序:

private static int[] withoutDuplicates(int[] a) {
    Arrays.sort(a);
    int hi = a.length - 1;
    int[] result = new int[a.length];
    int j = 0;
    for (int i = 0; i < hi; i++) {
        if (a[i] == a[i+1]) {
            continue;
        }
        result[j] = a[i];
        j++;            
    }
    result[j++] = a[hi];
    return Arrays.copyOf(result, j);
}

2)如果你关心初始数组元素的顺序:

private static int[] withoutDuplicates2(int[] a) {
    HashSet<Integer> keys = new HashSet<Integer>();
    int[] result = new int[a.length];
    int j = 0;
    for (int i = 0 ; i < a.length; i++) {
        if (keys.add(a[i])) {
            result[j] = a[i];
            j++;
        }
    }
    return Arrays.copyOf(result, j);
}

3)如果你不关心初始数组元素的顺序:

private static Object[] withoutDuplicates3(int[] a) {
    HashSet<Integer> keys = new HashSet<Integer>();
    for (int value : a) {
        keys.add(value);
    }
    return keys.toArray();
}

想象一下这是你的输入数据:

Index: 0, 1, 2, 3, 4, 5, 6, 7, 8
Value: 1, 2, 3, 3, 3, 3, 3, 3, 3

然后根据你的算法, tempa需要是:

Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, ....Exception!!!
Value: 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 5, 6, 7, 8, 6, 7, 8, 7, 8, 8

你为什么遇到这个问题? 因为第一组嵌套for循环不会阻止您尝试插入重复数组索引的重复项!

什么是最好的解决方案?

使用套装! 设置保证其中没有重复的条目。 如果您创建一个新的Set然后将所有数组项添加到它,Set将修剪重复项。 然后,这只是从Set回到数组的问题。

或者,这是一个非常C方式做同样的事情:

//duplicates will be a truth table indicating which indices are duplicates.
//initially all values are set to false
boolean duplicates[] = new boolean[items.length];
for ( int i = 0; i< numItems ; i++) {
    if (!duplicates[i]) { //if i is not a known duplicate
        for(int j = i + 1; j < numItems; j++) {
            if(items[i] ==items[j]) {
                duplicates[j] = true; //mark j as a known duplicate
            }
        }
    }
}

我留给你弄清楚如何完成。

import java.util.HashSet;

import sun.security.util.Length;


public class arrayduplication {
public static void main(String[] args) {
        int arr[]={1,5,1,2,5,2,10};
        TreeSet< Integer>set=new TreeSet<Integer>();
        for(int i=0;i<arr.length;i++){
            set.add(Integer.valueOf(arr[i]));
        }
        System.out.println(set);


    }

}

您已经使用num_items来绑定循环。 使用该变量也可以为tempa设置数组大小。

double tempa [] = new double [num_items];

您可以使用java.util.Set而不是在数组中执行此操作。

这是一个例子:

public static void main(String[] args)
{
    Double[] values = new Double[]{ 1.0, 2.0, 2.0, 2.0, 3.0, 10.0, 10.0 };
    Set<Double> singleValues = new HashSet<Double>();

    for (Double value : values)
    {
        singleValues.add(value);
    }
    System.out.println("singleValues: "+singleValues);
    // now convert it into double array
    Double[] dValues = singleValues.toArray(new Double[]{});
}

这是另一种不使用集合的替代方法,只有原始类型:

public static double [] removeDuplicates(double arr[]) {
    double [] tempa = new double[arr.length];
    int uniqueCount = 0;
    for (int i=0;i<arr.length;i++) {
        boolean unique = true;
        for (int j=0;j<uniqueCount && unique;j++) {
            if (arr[i] == tempa[j]) {
                unique = false;
            }
        }
        if (unique) {
            tempa[uniqueCount++] = arr[i];
        }
    }

    return Arrays.copyOf(tempa,  uniqueCount);
}

它确实需要一个临时的双重对象数组来获取实际结果。

您可以使用一组来删除倍数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM