例如......
调整此Array元素的最快方法是什么,以便它们符合上述标准?
如果最大出现次数接近于array,则我的第一个解决方案太慢了.Length(1M)/ valuesSpan(1000)
我尝试了类似的东西(这只是为了对齐最大出现次数,下限的解决方案几乎相同):
Int64[] DistinctArrayElements = distinctArrayElements;
Dictionary<Int64, Int32> occurrences = new Dictionary<Int64, Int32>();
foreach (Int64 DistinctElement in DistinctArrayElements)
{
occurrences.Add(DistinctElement, 0);
}
foreach (Int64 ArrayElement in Arr)
{
occurrences[ArrayElement] += 1;
}
//I know this initialization can be done more nicely, so don't bother with this.
for (int j = 0; j < Arr.Length; j++)
{
if (occurrences[Arr[j]] > upperNoOfOccurrences)
{
for (int i = 0; i < Arr.Length; i++)
{
if (occurrences[Arr[i]] < upperNoOfOccurrences)
{
Arr[j] = Arr[i];
occurrences[Arr[i]] += 1;
occurrences[Arr[j]] -= 1;
}
}
}
}
答案 0 :(得分:0)
我无法从你想做的事情中找到真正的意义。但是,多次处理阵列似乎是一种浪费。你可以只用一个循环(当你用完“免费”唯一值时稍微向前偷看)。以下当然不是我编写的最好的代码,但我认为它可以解决您的问题。
HashSet<long> forbidden = new HashSet<long>(); // maximum size of 1000, contains values that exceeded the limit
Queue<long> remaining = new Queue<long>(1000); // stores found unique values within the limit in a queue, that will be used if we bounce into the limit
Dictionary<long, int> frequencies = new Dictionary<long, int>(1000);
int lastPeekIndex = 0;
for (int i = 0; i < Arr.Length; i++) {
if (!frequencies.ContainsKey(Arr[i])) {
frequencies[Arr[i]] = 0;
remaining.Add(Arr[i]);
}
if (frequencies[Arr[i]] == upperLimit) {
if (!forbidden.Contains(Arr[i])) forbidden.Add(Arr[i]);
var next = Int64.MinValue;
try {
next = remaining.Dequeue();
while (forbidden.Contains(next)) next = remaining.Dequeue();
} catch (InvalidOperationException) { // Arrr! we have not yet observed enough unique values
for (int j = Math.Max(i, lastPeekIndex) + 1; j < Arr.Length; j++)
if (!frequencies.ContainsKey(Arr[j])) {
frequencies[Arr[j]] = 0;
next = Arr[j];
lastPeekIndex = j;
}
}
Arr[i] = next;
frequencies[next]++;
if (frequencies[next] < upperLimit) remaining.Enqueue(next);
} else frequencies[Arr[i]]++;
}
请注意,这不会检查下限,因为您也没有检查。我认为你必须关心在第二次传球中不经常出现的价值。您可以在第一次传递后将它们放在另一个队列中,然后一次又一次地遍历数组,直到队列为空(在第二次传递中可能甚至少于一次完整的迭代)。
答案 1 :(得分:0)
我会对你的字典进行排序,以便首先显示较少的数字。这样,您不必每次都查找合适的数字,只需将其替换为具有较少出现次数的数字。这是一个伪代码来解释:
struct dict {
key, value
}
linkedList<dict> occurrences;
initialize occurrences
sort it (smallest values first)
// start from the one with greatest number of occurrences
n = occurrences.last;
// keep going until occurrences of n is greater than upperNoOfOccurrences
while n.value.value > upperNoOfOccurrences and didn't reach first element
repeat = true
do:
// required occurrences to subtract to be within the limit
required = upperNoOfOccurrences - n.value.value
// maximum occurrences we can add to the first
maxAllowed = upperNoOfOccurrences - occurrences.first.value.value
// if we can do that
if required < maxAllowed:
occurrences.first.value.value += required
n.value.value -= required
repeat = false
else: // n.value.value is still greater than upperNoOfOccurrences
occurrences.first.value.value += maxAllowed
n.value.value -= maxAllowed
repeat = true
end if
// keep occurrences sorted
newPos = occurrences.first.next
while occurrences.first.value > newPos.value.value:
newPos = newPos.next
move occurrences.first before newPos
while repeat
end while
now rebuild your array with occurrences. it will
be sorted but it doesn't matter does it? ;)
答案 2 :(得分:0)
这是一个简单而精确的方法,可以统一采样符合您标准的数字集。
i
直到M,设置T [i] = L + S [i D] + S [i D + 1] + ... + S [i * d + d-1]。i
的T [i]个实例每个i
的价值。因为S包含N 1,所以V将完全准确地填充。注意步骤2-5是O(M D),而6-7是O(N + M),后者和可以实现的一样好,前者可能同样如此,因为M < / em> D在您的问题陈述中是O(N)。