C# 确定数组是否包含重复值的最快方法是什么?
阵列只能有一个副本或根本没有副本 我需要算法通过一些单元测试,并有不同版本的不同测试失败 如果您能发现这两种解决方案的任何错误或知道任何更快的解决方案,我将不胜感激 散列: 这会使大小为UInt16.MaxValue的数组的持续时间测试失败,该数组包含或不包含重复值 已传递-空数组不包含重复项C# 确定数组是否包含重复值的最快方法是什么?,c#,arrays,performance,time,duplicates,C#,Arrays,Performance,Time,Duplicates,阵列只能有一个副本或根本没有副本 我需要算法通过一些单元测试,并有不同版本的不同测试失败 如果您能发现这两种解决方案的任何错误或知道任何更快的解决方案,我将不胜感激 散列: 这会使大小为UInt16.MaxValue的数组的持续时间测试失败,该数组包含或不包含重复值 已传递-空数组不包含重复项 已通过-无重复的小数组 已通过-带重复的小数组(重复) 已通过-带重复的小数组(重复) 已通过-无重复的大型阵列(重复) 失败-无重复的大型阵列(持续时间) 已通过-重复的大数组(重复) 已通过-重复的大
已通过-无重复的小数组
已通过-带重复的小数组(重复)
已通过-带重复的小数组(重复)
已通过-无重复的大型阵列(重复)
失败-无重复的大型阵列(持续时间)
已通过-重复的大数组(重复)
已通过-重复的大数组(重复)
失败-重复的大型阵列(持续时间)
失败-合并
public bool ContainsRepeat(UInt16[] values, out UInt16 repeat)
{
//HASH SET//
var set = new HashSet<UInt16>();
repeat = 0;
foreach (UInt16 value in values)
{
if (!set.Add(value))
{
repeat = value;
return true;
}
}
return false;
}
public bool ContainsRepeat(UInt16[] values, out UInt16 repeat)
{
int findRepeatingElement(UInt16[] arr, int low, int high)
{
if (low > high)
return -1;
int mid = (low + high) / 2;
if (arr[mid] != mid + 1)
{
if (mid > 0 && arr[mid] == arr[mid - 1])
return mid;
return findRepeatingElement(arr, low, mid - 1);
}
return findRepeatingElement(arr, mid + 1, high);
}
repeat = 0;
if (values.Length <= 1)
{
return false;
}
Array.Sort(values);
int index = findRepeatingElement(values, 0, values.Length - 1);
if (index != -1)
{
repeat = values[index];
return true;
}
else
{
return false;
}
}
public bool包含重复(UInt16[]值,out UInt16 repeat)
{
//散列集//
var set=新的HashSet();
重复=0;
foreach(UInt16值以值表示)
{
如果(!set.Add(value))
{
重复=数值;
返回true;
}
}
返回false;
}
排序,然后对副本进行二进制搜索:
对于大小为UInt16.MaxValue的同一数组,这会使持续时间测试失败,但仅当没有重复时才会失败,而且在有重复时也无法返回正确的重复值,即使它适用于较小的数组
已传递-空数组不包含重复项已通过-无重复的小数组
已通过-带重复的小数组(重复)
已通过-带重复的小数组(重复)
已通过-无重复的大型阵列(重复)
失败-无重复的大型阵列(持续时间)
已通过-重复的大数组(重复)
失败-重复的大型阵列(重复)
已通过-重复的大数组(持续时间)
失败-合并
public bool ContainsRepeat(UInt16[] values, out UInt16 repeat)
{
//HASH SET//
var set = new HashSet<UInt16>();
repeat = 0;
foreach (UInt16 value in values)
{
if (!set.Add(value))
{
repeat = value;
return true;
}
}
return false;
}
public bool ContainsRepeat(UInt16[] values, out UInt16 repeat)
{
int findRepeatingElement(UInt16[] arr, int low, int high)
{
if (low > high)
return -1;
int mid = (low + high) / 2;
if (arr[mid] != mid + 1)
{
if (mid > 0 && arr[mid] == arr[mid - 1])
return mid;
return findRepeatingElement(arr, low, mid - 1);
}
return findRepeatingElement(arr, mid + 1, high);
}
repeat = 0;
if (values.Length <= 1)
{
return false;
}
Array.Sort(values);
int index = findRepeatingElement(values, 0, values.Length - 1);
if (index != -1)
{
repeat = values[index];
return true;
}
else
{
return false;
}
}
public bool包含重复(UInt16[]值,out UInt16 repeat)
{
int findRepeatingElement(UInt16[]arr,int低,int高)
{
如果(低>高)
返回-1;
int mid=(低+高)/2;
如果(arr[mid]!=mid+1)
{
如果(mid>0&&arr[mid]==arr[mid-1])
中途返回;
返回findRepeatingElement(arr、low、mid-1);
}
返回findRepeatingElement(arr,中+1,高);
}
重复=0;
if(values.Length创建UInt16.MaxValue元素的新布尔数组。使用此数组(而不是哈希集)作为探测,以标记看到的值并检测后续的重复项
public bool ContainsRepeat(UInt16[] values, out UInt16 repeat)
{
var seen = new bool[UInt16.MaxValue]; // O(k) space/time; fixed with very small C
foreach (UInt16 value in values) // O(n) time; n <= k, with small C
{
if (seen[value]) {
repeat = value;
return true;
}
seen[value] = true;
}
repeat = 0;
return false;
}
public bool包含重复(UInt16[]值,out UInt16 repeat)
{
var seen=new bool[UInt16.MaxValue];//O(k)空间/时间;用非常小的C修复
例如,foreach(UInt16 value in values)//O(n)time;nn),因此需要支付恒定的初始化和内存成本
这一特征类似于一般排序,并与一般排序相关的空间与时间权衡
也可以应用微优化(确保在实际条件下进行基准测试)。清除现有数组与创建新数组;或使用int和increment+check与boolean-check+set;或使用不安全来避免索引范围保护
如果在“大型”阵列的情况下失败……祝“最快”好运。为什么,除了创建一个40亿成员的阵列之外,还必须有其他选择?具体问题是“最快”对于UInt16范围:这种方法同样是专门化的,就像选择基数排序而不是一般的合并排序一样。那么这与一个巨大的数组有什么关系呢?请在您的答案中解释一下。经过澄清更新。非常感谢您,我以前用int的探测数组尝试过这种方法,但总是出现越界异常,还有stupidly,从未想过将大小增加到原始阵列的长度之外这些失败的测试是否会引发任何异常?没有,但持续时间必须小于2毫秒