Link where I got the problem from
我正在尝试一种O(n²)解决方案,以查找在给定数组中哪些元素出现的次数比n / k次(if (count > (arr.Length / k))
条件可以解决此问题。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4, count = 1;
for(int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (arr.Length / k))
{
Console.WriteLine(arr[i] + " " + i);
count = 1;
}
}
}
}
输出:
3 0
2 2
2 3
答案 0 :(得分:1)
问题在于,只有在存在匹配项且count
大于count
时,您才重置arr.Length/k
。您需要在内部for
循环的结尾处重置它,或者最好在内部for
循环之前对其进行定义,因为在该循环之外不需要它。另外,我猜想您会在count
满足条件后立即退出该循环,否则您将继续写出相同的内容。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
for(int i = 0; i < arr.Length; i++)
{
int count = 1;
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (arr.Length / k))
{
Console.WriteLine(arr[i] + " " + i );
break;
}
}
}
}
但是,这仍然会在其他位置产生重复值的结果。例如,数组k等于4的{3,1,2,2,1,2,3,3,3,3,3,3}产生3,0; 3,6; 3,7;和3,8。假设您只想要3.0,那么一个更好的解决方案是。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
var results = arr.Select((x,i) => new {Value = x, Index = i})
.GroupBy(x => x.Value)
.Where(grp => grp.Count() > arr.Length / k)
.Select(grp => grp.First());
foreach(var r in results)
{
Console.WriteLine($"{r.Value} {r.Index}");
}
或者,如果您更喜欢使用for
循环而不是Linq,那么您只需要一个HashSet<int>
来跟踪已经看到的值即可。
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
HashSet<int> seen = new HashSet<int>();
for(int i = 0; i < arr.Length; i++)
{
if(!seen.Add(arr[i]))
{
continue;
}
int count = 1;
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (arr.Length / k))
{
Console.WriteLine(arr[i] + " " + i );
break;
}
}
}
}
请注意,当值已经在哈希集中时,Add
返回false。
答案 1 :(得分:0)
这不是最优化的方法吗?因为您不想检查最后的arr.Length/k
个元素,因为如果所有元素都相同,那么它们在数量上只会是are.Length/k
而不是> are.Length/k
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int k = 4;
int target = arr.Length/k;
for(int i = 0; i < arr.Length - target; i++)
{
int count = 1;
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] == arr[j])
{
count++;
if (count > (target))
{
Console.WriteLine(arr[i] + " " + i );
break;
}
}
}
}
如果您可以使用一种算法来排序O(n log n)
或更小,那么类似的事情可能会有用:
int[] arr = { 3, 1, 2, 2, 1, 2, 3, 3 };
int[] sorted = Sort(arr); //sort method
int k = 4;
int target = arr.Length/k;
int count = 0;
for(int i = 0; i < arr.Length - target; i++)
{
count++;
if(arr[i] != arr[i+1])
{
if(count > target)
Console.WriteLine($"{arr[i]} {count}");
count = 0;
}
}