这是常见的技术面试问题之一,会问到初级程序员和软件工程师。在Java中,如何从数组中删除重复的内容也有很多变种,比如有时数组是排序的,有时是不排序的,或者是不排序的。有时,面试官会把一半以上的时间花在这个问题上,通过施加新的限制条件,如就地删除重复的元素或不使用任何额外的数据结构等,逐步增加难度。
Btw,如果你被允许使用Java的集合框架,那么这个问题就很容易解决。不过,如果你不被允许使用Set、Iterator和其他Java实用类,那么它就突然变成了一个棘手的算法问题。
总之,在谈论解决方案之前,让我们先了解一下这个问题。你给了一个未经排序的整数数组,你必须从其中删除所有重复的部分。
例如,如果输入数组是{22, 3, 22, 11, 24, 24, 4, 3},那么输出数组应该是{22, 3, 11, 24, 4},即必须从原数组中删除重复的元素22, 24和3。
我相信一开始他会让你解决这个问题,而不去管原来的顺序,但根据你的表现,他可能会要求你再做一次,但这次要保持原来的顺序。让我们看看解决这个问题的不同方法。
如何在Java中从未排序的数组中删除重复的内容
删除重复元素的第一种最简单的方法是在O(nlogn) 时间内使用QuickSort或MergeSort对数组进行排序,然后在O(n)时间内删除重复元素。对数组进行排序的一个好处是,重复的元素会聚集在一起,这样就很容易将它们删除。
顺便说一下,如果面试官提出一些限制条件,比如你不能对数组进行排序,或者在输出数组中必须保留元素的原始顺序,那么这个解决方案将无法工作。在这种情况下,我们需要
另一种从整数数组中删除重复的方法是使用二叉树。你可以使用数组中的数字构建一个二进制搜索树,并丢弃所有重复的数字。二进制树将只包含非重复的数值,你可以随后将其转换为数组。
然而,这个解决方案的缺点是,元素的原始顺序没有被保留下来。这个解决方案的时间复杂度是O(nLogn),因为在二叉树中插入一个节点需要O(LogN)的时间,而我们需要添加n个节点,其中n是数组的大小。
从未经排序的数组中删除重复内容的Java程序
现在让我们看看一个纯Java的解决方案,在这里你被允许使用Set接口。你通过使用HashSet或LinkedHashSet来解决这个问题。如果你被要求保留元素的顺序,那么你可以使用LinkedHashSet,因为它可以保持元素被添加到其中的顺序。
package tool;
import static org.junit.Assert.assertArrayEquals;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
public class DuplicateArray {
private Integer[] removeDuplicates(Integer[] input) {
if (input == null || input.length <= 0) {
return input;
}
Set<Integer> aSet = new HashSet<>(input.length);
// set will reject all duplicates
for (int i : input) {
aSet.add(i);
}
return aSet.toArray(new Integer[aSet.size()]);
}
@Test
public void testArrayWithDuplicates() {
Integer[] given = new Integer[] { 1, 2, 3, 3 };
Integer[] actual = removeDuplicates(given);
Integer[] expected = new Integer[] { 1, 2, 3 };
assertArrayEquals(expected, actual);
}
@Test
public void testArrayWithoutDuplicates() {
Integer[] given = new Integer[] { 1, 2, 3 };
Integer[] actual = removeDuplicates(given);
Integer[] expected = new Integer[] { 1, 2, 3 };
assertArrayEquals(expected, actual);
}
@Test
public void testWithEmptyArray() {
Integer[] given = new Integer[] {};
Integer[] actual = removeDuplicates(given);
Integer[] expected = new Integer[] {};
assertArrayEquals(expected, actual);
}
@Test
public void testWithNull() {
Integer[] given = null;
Integer[] actual = removeDuplicates(given);
Integer[] expected = null;
assertArrayEquals(expected, actual);
}
@Test
public void testArrayWithAllDuplicates() {
Integer[] given = new Integer[] { 3, 3, 3 };
Integer[] actual = removeDuplicates(given);
Integer[] expected = new Integer[] { 3 };
assertArrayEquals(expected, actual);
}
@Test
public void testArrayWithMultipleDuplicates() {
Integer[] given = new Integer[] { 1, 2, 3, 3, 4, 4, 5, 5, 5 };
Integer[] actual = removeDuplicates(given);
Integer[] expected = new Integer[] { 1, 2, 3, 4, 5 };
assertArrayEquals(expected, actual);
}
}
当你在Eclipse中以JUnit测试的形式运行这个程序时,你会看到如下的绿色条,这表明所有的测试用例都通过了,我们的解决方案工作正常。
这是一个很好的解决方案,也说明了智能使用数据结构可以使解决方案变得简单。这段代码简单易懂,而且在CPU时间方面也非常高效,因为你只需要O(n)时间就能解决这个问题。
Btw,如果面试官仍然提出另一个约束条件,要求你在不使用Java Collection API的情况下删除重复的内容,那么你别无选择,只能在数组上进行迭代,比较每一个元素,找到并删除重复的内容。 这里讨论了完整的解决方案,你也可以在尝试后看到。
以上就是关于如何在Java中从一个未排序的数组中删除重复的元素的全部内容。每个解决方案都是可以接受的,但都有其优点和缺点。最关键的是,你应该从时间和空间复杂度最高的方案开始,然后达到最高效的方案。这是我在面试中经常使用的技巧之一,把面试官带到我的强项上。
其他阵列编码问题练习
如果你对解决更多基于阵列的算法问题感兴趣,那么这里有一些面试中经常被问到的编码问题。
-
如何在一个整数数组上找到总和等于给定数的所有配对?[解决方案]
-
写一个程序,从一个整数数组中找出前两个数字?[解决方案]
-
30+ 面试中基于数组的编码问题(问题)
-
100+破解编程面试的编码问题(问题)
-
如何在Java中检查一个数组是否包含一个数字?[解决方案]
-
如何在原地删除数组中的重复部分?[解决方案]
-
如何解决Java中的二和问题?[解决方法)
-
如何在Java中从一个给定的数组中找出最大和最小的数字?[解决方法]
-
书评 - Grokking Algorithms(评论)
-
为程序员提供的10个免费数据结构和算法课程[课程]。
-
写一个程序来寻找1到100的整数数组中缺少的数字?[解决方案]
-
在Java中如何将一个数组原地倒转?[解决方案]
-
如何查找未排序数组中的最大和最小数?[解决方案]
-
破解编码面试的10门算法课程[课程]。
-
如何使用QuickSort算法对数组进行原地排序?[解决方案]
-
如何在Java中打印数组中所有重复的元素?[解决方案]
-
50+面试中的数据结构和算法编码问题(问题)
-
每个程序员都应该阅读的10本算法书籍[书籍]
谢谢你阅读这篇文章。如果你喜欢这个面试问题,那么请与你的朋友和同事分享它。如果你有任何疑问或反馈,那么请留言。

