从数组中删除重复项

时间:2014-07-21 22:29:59

标签: java algorithm

enter image description here

我正在从我的数据结构书中处理以下问题。我已经按照本文的建议提出了解决方案。我基本上找到了所有的重复项,并将它们标记为666之类的任意数字,然后将它们从数组中删除。

我对每个人的问题是 - 我的解决方案是否与文本建议完全一致? - 什么是解决这个问题的更有效的方法?

这是完整的代码(在nodups方法中查看我的解决方案)

public class HighArray {

    private long[] a;
    private int nElems;

    public HighArray(int max) {

        a = new long[max];
        nElems = 0;
    }

    public boolean find(long searchKey) {
        int j;
        for (j = 0; j < nElems; j++)
            if (a[j] == searchKey)
                break;

        if (j == nElems) {
            return false;
        }

        else {
            return true;
        }
    }

    public void insert(long value) {

        a[nElems] = value;
        nElems++;
    }

    public void noDups() {
        int i = 0;
        long compareKey;

        while (i < nElems) {

            compareKey = a[i];

            for (int j = 0; j < nElems; j++) {
                if (j != i && a[j] != 666) {
                    if (a[j] == compareKey) {
                        a[j] = 666;
                    }
                }
                j++;
            }

            i++;
        }

        for (int k = 0; k < nElems; k++) {
            if (a[k] == 666) {
                delete(a[k]);
            }
        }

    }

    public boolean delete(long value) {

        int j;
        for (j = 0; j < nElems; j++)
            if (a[j] == value)
                break;

        if (j == nElems) {
            return false;
        }

        else {
            for (int k = j; k < nElems - 1; k++)
                a[k] = a[k + 1];
            nElems--;
            return true;
        }
    }

    public long removeMax() {

        if (nElems != 0) {
            long maxValue = a[0];

            for (int i = 0; i < nElems; i++) {
                if (a[i] > maxValue)
                    maxValue = a[i];
            }

            delete(maxValue);
            return maxValue;
        }

        else {
            return -1;
        }
    }

    public void display() {

        for (int i = 0; i < nElems; i++) {
            System.out.println(a[i]);
        }
    }

}

以下课程有主要方法。

public class HighArrayApp {

    public static void main(String[] args) {

        HighArray arr = new HighArray(100);

        arr.insert(2);
        arr.insert(2);
        arr.insert(3);
        arr.insert(4);
        arr.insert(4);
        arr.insert(5);

        arr.display();

        arr.noDups();

        System.out.println("-------------------------");

        arr.display();

    }

}

我非常感谢任何建议,我对各种方法持开放态度,尝试为这个问题提供更有效的算法。

5 个答案:

答案 0 :(得分:4)

你的解决方案是有效的,但正如你所说,我认为有一种更有效的方法。我也认为给定的文字意味着这一点(&#34;一种方法是......&#34; &#34;另一种方法是...&#34; )。

将每个元素与其他元素进行比较是O(n^2)

如果您首先对数组进行排序,则可以通过数组中的单个步骤删除重复项。

排序为O(n log n),遍历为O(n)

总复杂度为O( n log n) + O(n) = O(n log n)

此解决方案有效,因为文本明确指出可能会更改对象的顺序。

答案 1 :(得分:3)

您可以使用Lambda Expression

以更少的代码完成此操作

代码:

public class LambdaTest     
{
    public static void main (String[] args)
    {

         List<Integer> objList = Arrays.asList(1,1,2,3,2,4,5,2,5);
         objList .forEach(i -> System.out.print(" " + i));
         System.out.println();
         List<Integer> noDub =objList.stream().distinct().collect(Collectors.toList());
         noDub.forEach(i -> System.out.print(" " + i));
    } 
}

输出:

1 1 2 3 2 4 5 2 5 

1 2 3 4 5

答案 2 :(得分:2)

您可以为此使用更好,更快的数据结构。为什么不使用HashSet?

实施例

import java.util.*;

public class Test
{
    public static void main(String[]args)
    {
        Integer [] arr = new Integer[]{4, 3, 1, 2, 4, 3, 2};
        Set<Integer> hs = new HashSet<Integer>(Arrays.asList(arr));
        System.out.println(hs);
    }
}

答案 3 :(得分:1)

你的功能按照文本的含义执行,不幸的是,这是一种可怕的方式。

首先,你假设666不是一个可能的值,这可能是假的,并且在设计中即使它是暂时的,可能随着你的程序的未来变化而改变。

其次,如果您希望从列表中添加和删除,HighArray类不应该保留long数组。由于项目的顺序很重要,因此ArrayList或您自己的链接列表实现更合适。

如果必须使用给定的HighArray类,那么最简单的方法是将数组a转换为HashSet,它将跟踪所有唯一值。然后将HashSet转回数组。

Set<Long> uniqueNumbers = new HashSet<Long>(Arrays.asList(a));
a = uniqueNumbers.toArray(new long[uniqueNumbers.size()]);

创建和管理集合的总体复杂度为O(n lg(n)),并将其转换回数组O(n),这比原始方法的O(n^2)复杂度要好得多。

答案 4 :(得分:1)

本书中描述的算法类似于冒泡排序。最简单的方法是使用两个嵌套循环。


for (int i=0; i < a.length;i++) {
    long ref = a[i];
    for (int j=i+1; j < a.length; j++) {
        if(a[j] == ref) {
            a[j] = Long.MIN_VALUE;
        }
    }
}

我遗漏了清理部分。