我正在从我的数据结构书中处理以下问题。我已经按照本文的建议提出了解决方案。我基本上找到了所有的重复项,并将它们标记为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();
}
}
我非常感谢任何建议,我对各种方法持开放态度,尝试为这个问题提供更有效的算法。
答案 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;
}
}
}
我遗漏了清理部分。