C ++: creating a function using an array

Write a function that has:

input: array of pairs (unique id and weight) length of N, K =< N  
output: K random unique ids (from input array)  

Note: when calling many times, the frequency of occurrence of any Id in the output should be more than more weight. Example: an identifier with a weight of 5 should appear on the output 5 times more often than an id with a weight of 1. In addition, the amount of allocated memory should be known at compile time, that is, no additional memory should be allocated.

My question is: how to solve this problem?

CHANGE
thanks for all answers!
currently I can’t understand how the weight of a pair affects the frequency of a pair appearing in the output, can you give me a clearer “explanation” of how this works? "

+5
source share
5 answers

: .

, . Axn :

. , K <= N. K N, . , K = N, (.. ), .

, K N, .

:

  • ( )

  • (sumOfWeights)
  • [1; sumOfWeights]
  • ,

#include <iostream>
#include <cstdlib>
#include <ctime>

// 0 - id, 1 - weight
typedef unsigned Pair[2];

unsigned Random(Pair* i_set, unsigned* i_indexes, unsigned i_size)
{
   unsigned sumOfWeights = 0;
   for (unsigned i = 0; i < i_size; ++i)
   {
      const unsigned index = i_indexes[i];
      sumOfWeights += i_set[index][2];
   }

   const unsigned random = rand() % sumOfWeights + 1;

   sumOfWeights = 0;
   unsigned i = 0;
   for (; i < i_size; ++i)
   {
      const unsigned index = i_indexes[i];
      sumOfWeights += i_set[index][3];
      if (sumOfWeights >= random)
      {
         break;
      }
   }

   return i;
}

-- . . .

N , , N , .

. Random() rand() .

template<unsigned N, unsigned K>
void Generate(Pair (&i_set)[N], unsigned (&o_res)[K])
{
   unsigned deck[N];
   for (unsigned i = 0; i < N; ++i)
   {
      deck[i] = i;
   }

   unsigned max = N - 1;

   for (unsigned i = 0; i < K; ++i)
   {
      const unsigned index = Random(i_set, deck, max + 1);

      std::swap(deck[max], deck[index]);
      o_res[i] = i_set[deck[max]][0];
      --max;
   }
}

int main()
{
   srand((unsigned)time(0));

   const unsigned c_N = 5;    // N
   const unsigned c_K = 2;    // K
   Pair input[c_N] = {{0, 5}, {1, 3}, {2, 2}, {3, 5}, {4, 4}}; // input array
   unsigned result[c_K] = {};

   const unsigned c_total = 1000000; // number of iterations
   unsigned counts[c_N] = {0};       // frequency counters

   for (unsigned i = 0; i < c_total; ++i)
   {
      Generate<c_N, c_K>(input, result);
      for (unsigned j = 0; j < c_K; ++j)
      {
         ++counts[result[j]];
      }
   }

   unsigned sumOfWeights = 0;
   for (unsigned i = 0; i < c_N; ++i)
   {
      sumOfWeights += input[i][1];
   }

   for (unsigned i = 0; i < c_N; ++i)
   {
      std::cout << (double)counts[i]/c_K/c_total  // empirical frequency
                << " | "
                << (double)input[i][1]/sumOfWeights // expected frequency
                << std::endl;
   }

   return 0;
}

N = 5, K = 2

      Frequencies
Empiricical | Expected
 0.253813   | 0.263158
 0.16584    | 0.157895
 0.113878   | 0.105263
 0.253582   | 0.263158
 0.212888   | 0.210526

,

N = 5, K = 5

      Frequencies
Empiricical | Expected
 0.2        | 0.263158
 0.2        | 0.157895
 0.2        | 0.105263
 0.2        | 0.263158
 0.2        | 0.210526
+2

:

  • (total_weight)
  • K :
    • 0 total_weight (selection)
    • , selection

.

+7

, :

(3, 7)
(1, 2)
(2, 5)
(4, 1)
(5, 2)

, , .. :

3 3 3 3 3 3 3 1 1 2 2 2 2 2 4 5 5

, , , up = X, = 17

[0, X-1] , , . , 8

(3, 7) total = 7 which is < 8
(1, 2) total = 9 which is >= 8 **boom** 1 is your id!

, K random unique, - , . , . : - ! , . , .

, K, <= N , : O (2 * )

:

O(n) : create copy of original array into hastable +
(
   O(n) : calculate sum of weights +
   O(1) : calculate random between range +
   O(n) : cumulative totals
) * K random pickings
= O(n*k) overall

:)

+5

(..: = O (1)). , , , , .

  • , , . .

  • sum_weights = n = N.

  • K :

    • r [0, sum_weights]

    • n , ( ) r, i.

    • [i].id .

    • [i-1].weight [i].weight( == 0). [i].weight ( > i) , sum_weight.

    • [i] ​​ [n-1] ( ). , O (N), K . .

    • 1 n

  • n-1 1,

- O (K * N). ( ) . , , .

Update

, ": K ". , , /, , :

  • , , . .

  • sum_weights = n = N.

  • K :

    • r [0, sum_weights]

    • n , ( ) r, i.

    • [i].id .

  • n-1 1,

- O (K * log (N)).

+3

, . .

, , O (N ^ 2) , O (N) ( ). , .

A - .

1) N A.

2) W.

3) K

    3.1) r = rand (0, W)

  3.2) A , A [1].w +... + A [i].w <= r < A [1].w +... + A [i + 1].w

    3.3) A [i].id

    3.4) A [i] = A [N-1] ( , )

    3.5) N = N - 1

    3.6) W = W - A [i].w

+1

All Articles