C# 在具有单个循环的数组中查找重复项
问题是存在和未排序的数组,最大值应小于长度。我必须在数组中找到重复的记录。条件是只使用一次循环。这就是我迄今为止所取得的成就。我想知道是否有其他方法可以实现这一目标C# 在具有单个循环的数组中查找重复项,c#,arrays,algorithm,C#,Arrays,Algorithm,问题是存在和未排序的数组,最大值应小于长度。我必须在数组中找到重复的记录。条件是只使用一次循环。这就是我迄今为止所取得的成就。我想知道是否有其他方法可以实现这一目标 int[] Arr = { 9, 5, 6, 3, 8, 2, 5, 1, 7, 4 }; int[] Arr2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; for (int i = 0; i < Arr.Length; i++) { if (Arr2[Arr[i]] == 0) {
int[] Arr = { 9, 5, 6, 3, 8, 2, 5, 1, 7, 4 };
int[] Arr2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (int i = 0; i < Arr.Length; i++)
{
if (Arr2[Arr[i]] == 0)
{
Arr2[Arr[i]] = Arr[i];
}
else
{
Console.WriteLine("duclicate found");
}
}
int[]Arr={9,5,6,3,8,2,5,1,7,4};
int[]Arr2={0,0,0,0,0,0,0,0,0,0};
对于(int i=0;i
使用任何集
实现,比如哈希集
,例如
HashSet<int> hs = new HashSet<int>();
int[] Arr = { 9, 5, 6, 3, 8, 2, 5, 1, 7, 4 };
foreach (item in Arr)
if (hs.Contains(item)) {
Console.WriteLine("duplicate found");
// break; // <- uncomment this if you want one message only
}
else
hs.Add(item);
这是最新的
如果没有额外的空间,这个问题不能严格线性地解决
解决该问题的两种常见方法是:
O(nlogn)
时间和很少的额外空间使用LINQ获取所有副本的最快方法是:
var duplicates = Arr.GroupBy(s => s).SelectMany(d => d.Skip(1));
这将返回Arr
中所有重复元素的IEnumerable
,您可以使用以下检查来包含是否存在任何重复项:
if (duplicates.Any())
{
// We have a duplicate!
}
如果只有数组
a[]
包含范围[0,n-1]
{如您的问题所示}
中的数字,并且n不是非常大,以避免整数范围溢出,那么这将起作用
for(i=0;i<n;i++)
{
if(a[a[i]%n]>=n)
**duplicate is a[i]** !
else
a[a[i]%n]+=n;
}
(i=0;i=n)的
**重复是一个[i]**!
其他的
a[a[i]%n]+=n;
}
时间复杂度:O(N)空间复杂性:O(1) 使用LINQ尝试此代码
int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 };
var duplicates = listOfItems
.GroupBy(i => i)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
foreach (var d in duplicates)
Console.WriteLine("The duplicate is "+d);
由于您有这种情况:
问题是存在和未排序的数组,最大值应小于长度。
另外,假设只有正数
数字,在您的示例中适用
这可以使用O(n)
时间和O(1)
空间来完成,而无需使用任何LINQ、字典、哈希等
int[] arr = { 9, 5, 6, 3, 8, 2, 5, 1, 7, 4 };
for (int i = 0; i < arr.Length; i++)
{
if (arr[Math.Abs(arr[i])] >= 0)
arr[Math.Abs(arr[i])] = -arr[Math.Abs(arr[i])];
else
Console.WriteLine("Duplicate found " + Math.Abs(arr[i]).ToString() + "\n");
}
int[]arr={9,5,6,3,8,2,5,1,7,4};
对于(int i=0;i=0)
arr[Math.Abs(arr[i])]=-arr[Math.Abs(arr[i]);
其他的
Console.WriteLine(“找到重复项”+Math.Abs(arr[i]).ToString()+“\n”);
}
使用集合而不是第二个数组。在添加到集合之前,请检查集合是否包含该元素-如果包含,则有一个副本。或者您可以只检查Add
中的返回值-如果它是false
,元素已经存在。您能给我一个例子吗?它与当前的方法有什么不同?以前从未使用过C,但设置了≠ 数组,在大多数编程语言中,一个集合意味着一个HashSet,在它的每个元素上强制一个唯一的约束。然后你的前提条件确保了一定有重复。考虑长度为2的数组,它只能是{ 1, 1 }。这是相同的方法吗?是的,你的方法使用散列。但我建议保留一个位数组而不是int数组,以减少内存开销。@Muneeb Zulfiqar:它可以处理任意整数,比如“int[]Arr={5559,-2225,-56,23,-56};”@Mohit Jain:No;这个解决方案适用于任意整数,比如“int[]Arr={5559,-2225,-56,23,-56};”,这就是为什么我不想使用bitarray@Dmitry是的,你是对的。我说的不是实现,而是散列的概念。这个想法基本上是一样的。我更喜欢您的整数集方式,这样我的解决方案就可以在完整的整数范围内运行。使用哈希或BST实现的集合。对于这样小的内存,当您不使用标准功能并自行实现时(可能需要学习,或者数组边界已知),我建议首选位集合。条件是只循环一次。如何在单个循环中进行排序和比较?@MuneebZulfiqarforeach(Arr.OrderBy(s=>s)中的变量a)
OrderBy此循环多次sir@MuneebZulfiqar这个答案的目的是向你们表明,并不是我们想要的一切都能做到。如果没有额外的空间,这个问题不可能在一个循环中解决,这应该给你一个提示,你走在正确的轨道上。@amit我也有同样的想法,我只是需要一些专家的意见:)Linq不能使用。因为它会违反使用单循环的条件。@MuneebZulfiqar你是对的,GroupBy
实际上循环三次只是为了排序。:)
int[] arr = { 9, 5, 6, 3, 8, 2, 5, 1, 7, 4 };
for (int i = 0; i < arr.Length; i++)
{
if (arr[Math.Abs(arr[i])] >= 0)
arr[Math.Abs(arr[i])] = -arr[Math.Abs(arr[i])];
else
Console.WriteLine("Duplicate found " + Math.Abs(arr[i]).ToString() + "\n");
}