过滤数组中重复元素,你知道最优方案吗?

在这里插入图片描述

大家好,今天我们来研究一个比较常见的编码问题。 假如现在给我们一个对象数组,它可以是整数数组和字符串数组,也可以是实现 Comparable 接口的任何对象。

带着以下问题,我们来开始今天的文章:

  • 我们如何从数组中找到重复的元素?
  • 你能用 O(n) 复杂度来解决这个问题吗?

不论在日常工作中,或者在面试中,这都是经常遇到的问题;

其实有多种方法可以解决这个问题,在这里我们将讨论两种比较常见的方法,首先是常规方法,这种方法指将每个元素与其他元素进行比较,其次是使用类似哈希表的数据结构来将问题的时间复杂度从二次降低到线性,当然要增加一些空间复杂度。这也说明通过使用合理的数据结构,我们可以想出更优时间复杂度的算法来解决问题,所以说数据结构和算法的相关知识对程序员非常重要;

方案1- 在 O(n^2)中寻找重复项

在第一种解决方案中,我们将数组中的每个元素与其他每个元素进行比较。 如果它们相同,那么就有重复项,如果不相同,那么就没有重复项,通常把这种方法称为:暴力破解算法

当我们使用这种方案从数组中寻找重复项时,它的时间复杂度就是O (n ^ 2)

1 public static Set<Integer> findDuplicates(int[] input) { 2 Set<Integer> duplicates = new HashSet<Integer>(); 3 4 for (int i = 0; i < input.length; i++) { 5 for (int j = 1; j < input.length; j++) { 6 if (input[i] == input[j] && i != j) { 7 // duplicate element found 8 duplicates.add(input[i]); 9 break; 10 } 11 } 12 } 13 14 return duplicates; 15 }

我们将最后的重复项放入到Set集合返回,但是如果面试官问你还有其他优化方案吗?将它的时间复杂度降为O(n);

我们接着往下看

方案2 - 在 O(n) 中寻找重复项

第二个解决方案演示了如何使用合适的数据结构编写更好的算法来解决同样的问题。 我们知道,在 Java 中,由于Set 集合底层是基于散列表数据结构所以不允许重复元素,因此平均情况下插入需要 O(1)

通过HashSet集合来解决这个问题,我们可以在O(n)时间内完成,我们在for循环中将每个元素插入HashSet中,因为它只允许唯一的元素,所以当我们尝试添加重复元素时候,add()方法会返回false;

最后,我们将重复下打印出来,看看是不是可以实现我们的需求;

1public static <T extends Comparable<T>> void getDuplicates(T[] array) { 2 Set<T> dupes = new HashSet<T>(); 3 for (T i : array) { 4 if (!dupes.add(i)) { 5 System.out.println("Duplicate element in array is : " + i); 6 } 7 } 8 9 }

这个方法适用于Java中任何类型的 Java 数组,比如 Array with IntegerArray with String 或者任何实现 Comparable 接口的对象,但是不适用于原语数组,因为它们在 Java 中不是对象

代码清单

为了方便大家测试,提供了代码清单,大家可以直接跑一跑

1package com.milo.collection.list; 2 3import java.util.Arrays; 4import java.util.HashSet; 5import java.util.Set; 6 7/** 8 * 过滤数组中重复的元素 9 * @author milogenius 10 * @date 2020/4/22 23:03 11 */ 12public class DuplicatesFromArray { 13 public static void main(String args[]) { 14 int[] withDuplicates = { 1, 2, 3, 1, 2, 3, 4, 5, 3, 6 }; 15 //调用常规方法 16 Set<Integer> duplicates = findDuplicates(withDuplicates); 17 System.out.println("input array is : " + Arrays.toString(withDuplicates)); 18 System.out.println("Duplicate elements found in array are : " + duplicates); 19 20 // 调用泛型方法 21 String[] myArray = { "ab", "cd", "ab", "de", "cd" }; 22 System.out.println("input string array is : " + Arrays.toString(myArray)); 23 getDuplicates(myArray); 24 } 25 26 /** 27 * 时间复杂度是O(n²) 28 * 29 * @param input 30 * @return 31 */ 32 public static Set<Integer> findDuplicates(int[] input) { 33 Set<Integer> duplicates = new HashSet<Integer>(); 34 35 for (int i = 0; i < input.length; i++) { 36 for (int j = 1; j < input.length; j++) { 37 if (input[i] == input[j] && i != j) { 38 // 发现重复元素 39 duplicates.add(input[i]); 40 break; 41 } 42 } 43 } 44 45 return duplicates; 46 } 47 48 /** 49 * 时间复杂度为O(n) ,因为我们使用了HashSet数据结构 50 * 51 * @param array 52 * @return 53 */ 54 public static <T extends Comparable<T>> void getDuplicates(T[] array) { 55 Set<T> dupes = new HashSet<T>(); 56 for (T i : array) { 57 if (!dupes.add(i)) { 58 System.out.println("Duplicate element in array is : " + i); 59 } 60 } 61 62 } 63 64 65} 66 67 68Output : 69input array is : [1, 2, 3, 1, 2, 3, 4, 5, 3, 6] 70Duplicate elements found in array are : [1, 2, 3] 71input string array is : [ab, cd, ab, de, cd] 72Duplicate element in array is : ab 73Duplicate element in array is : cd

总结

我们学习了两种解决如何在数组中找到重复元素的方法,第一个解决方案是暴力破解算法,第二个解决方案是我们使用HashSet数据结构将第一种方案的时间复杂度从O(n^2)降为O (n),同时也展示了利用泛型实现方法的通用性;

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang

Java开发者容易犯的十个错误

!(https://oscimg.oschina.net/oscnet/c9f00cc918684fbe8a865119d104090b.gif)Top1.数组转换为数组列表将数组转换为数组列表,开发者经常会这样做:\java\List<StringlistArrays.asList(arr);Arr