Каков самый быстрый способ вычисления частотного распределения для массива в C#?

Мне просто интересно, что лучший подход для этого расчета. Предположим, у меня есть входной массив значений и массив границ - я хотел вычислить/bucketize частотное распределение для каждого сегмента в массиве границ.

Это хорошая идея использовать поиск ведра для этого?

на самом деле я нашел этот вопрос расчет частоты распределения коллекция .Чистый/С#

но я не понимаю как пользоваться ведрами для этой цели размер каждого ведра может быть разным в моей ситуации.

изменить: После всех обсуждений у меня есть решение внутреннего/внешнего цикла, но все же я хочу исключить внутренний цикл со словарем, чтобы получить производительность O(n) в этом случае, если я правильно понял, мне нужно хэшировать входные значения в индекс ведра. Итак, нам нужна какая-то хэш-функция со сложностью O(1)? Есть идеи, как это сделать?

2 ответов


сортировка ведра уже o (n^2) в худшем случае, поэтому я бы просто сделал простой внутренний/внешний цикл здесь. Поскольку Ваш массив ведра обязательно короче, чем ваш входной массив, держите его во внутреннем цикле. Поскольку вы используете пользовательские размеры ведра, на самом деле нет математических трюков, которые могут устранить этот внутренний цикл.

int[] freq = new int[buckets.length - 1];
foreach(int d in input)
{
    for(int i = 0; i < buckets.length - 1; i++)
    {
         if(d >= buckets[i] && d < buckets[i+1])
         {
             freq[i]++;
             break;
         }
    }
}

это также o (n^2) Худший случай, но вы не можете победить простоту кода. Я бы не беспокоился об оптимизации, пока она не станет реальной проблемой. Если у вас больше bucket array, вы можете использовать какой-то двоичный поиск. Но, начиная с частотных распределений обычно


Если ваш входной массив представляет данные реального мира( с его шаблонами), а массив границ велик, чтобы повторять его снова и снова во внутреннем цикле, вы можете рассмотреть следующий подход:

  • прежде всего отсортируйте входной массив. Если вы работаете с реальными данными Я бы рекомендовал рассмотреть Timsort-Wiki для этого. Он обеспечивает очень хорошие гарантии представления для картин которые можно увидеть внутри практический данные.

  • пройдите через отсортированный массив и сравните его с первым значением в массиве границ:

    • если значение во входном массиве меньше, то счетчик частоты приращения границы для этой границы
    • если значение во входном массиве больше, то граница-перейдите к следующему значению в массиве границ и увеличьте счетчик для новой границы.

в коде это может выглядеть это:

Timsort(myArray);
int boundPos; 
boundaries = GetBoundaries(); //assume the boundaries is a Dictionary<int,int>()

for (int i = 0; i<myArray.Lenght; i++) {
  if (myArray[i]<boundaries[boundPos]) { 
     boundaries[boubdPos]++;
  }
  else {
    boundPos++;
    boundaries[boubdPos]++;
  }
}