如何高效地找出给定数组中重复元素的个数?
using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; public class Test { //找出数组中不重复的元素的个数 private static void Main(string[] args) { //构造一个包含大量重复元素的数组 int Count = 100000; string[] arr = new string[Count]; for (int i = 0; i < Count; i++) { arr[i] = Convert.ToString((i % Count) * (new Random().Next(0, 100)) % Count); } //采用不同的算法 ArrQuery arrObj; //记录执行时间(开始) //DateTime dtBegin = DateTime.Now; Stopwatch monitor = Stopwatch.StartNew(); //方法一 arrObj = new HashQuery(arr); Task t1 = new Task(arrObj.Query); t1.Start(); //等待任务结束 t1.Wait(); //不能用此方法(因为无法确定线程是否执行完毕,无法统计执行时间) //Thread th1 = new Thread(new ThreadStart(md1.HashQuery)); //th1.Start(); //记录执行时间(结束) //DateTime dtEnd = DateTime.Now; //TimeSpan ts = dtEnd.Subtract(dtBegin); monitor.Stop(); Console.WriteLine("哈希查找:不重复的元素有:{0} 个,用时:{1} 秒", arrObj.total, monitor.Elapsed.TotalSeconds); //记录执行时间(开始) monitor = Stopwatch.StartNew(); //方法二 arrObj = new NormalQuery(arr); Task t2 = new Task(arrObj.Query); t2.Start(); //等待任务结束 t2.Wait(); //记录执行时间(结束) monitor.Stop(); Console.WriteLine("普通查找:不重复的元素有:{0} 个,用时:{1} 秒", arrObj.total, monitor.Elapsed.TotalSeconds); Console.WriteLine("请按任意键退出..."); Console.ReadKey(); } } /// <summary> /// 找出数组中的相同元素 /// </summary> public abstract class ArrQuery { public ArrQuery() { } public ArrQuery(string[] arr) { this.arr = arr; } /// <summary> /// 原始数组 /// </summary> public string[] arr { get; set; } /// <summary> /// 存储不重复的元素个数 /// </summary> public int total { get; set; } /// <summary> /// 查找方法 /// </summary> public abstract void Query(); } /// <summary> /// 1. 哈希查找 /// </summary> public class HashQuery : ArrQuery { public HashQuery(string[] arr) : base(arr) { } public override void Query() { //使用C#中的HashSet对象 HashSet<string> hash = new HashSet<string>(); //利用HashSet不包含重复项,也不会自动排序的特点 Array.ForEach(this.arr, t => hash.Add(t)); //hash.UnionWith(arr); //IEnumerable<string> ie = hash.Union(arr); //计算集合中不重复的元素总数 this.total = hash.Count; } } /// <summary> /// 2. 普通查找 /// </summary> public class NormalQuery : ArrQuery { public NormalQuery(string[] arr) : base(arr) { } public override void Query() { int len = this.arr.Length; //新定义一个临时数组,用来标记重复项 int[] temp = new int[len]; //初始化临时数组中的元素 for (int i = 0; i < len; i++) { temp[i] = 0; } //查找重复项 for (int i = 0; i < len; i++) { //检查temp[i]没有被标记,才继续查找 if (temp[i] != -1) { for (int j = i + 1; j < len; j++) { if (temp[j] != -1) { if (this.arr[i] == this.arr[j]) { temp[j] = -1; //输出部分值,用于观察 //if (j > 100000 && j < 150009) // Console.WriteLine("arr[" + i + "]=" + arr[i] + // ", arr[" + j + "]=" + arr[j]); } } } } } int myCount = 0; //计算数组中不重复的元素总数 for (int i = 0; i < temp.Length; i++) { if (temp[i] != -1) myCount++; } this.total = myCount; } }
运行结果如下: