C++ 학습/C++ 코딩인터뷰[5장]

[5. 배열] 5.16 균등하지 않은 임의의 숫자 생성하기

msugi 2025. 1. 22. 16:31

[해당 문제는 266가지 문제로 정복하는 코딩 인터뷰]
책의 내용의 문제와 풀이를 베이스로 공부하는 내용이다. 

문제를 풀기전에 단순하게 문제를 푸는것이 목적이 아닌
시간복잡도와 공간복잡도의 관계를 계산하며,
자료구조의 이해도와 실력을 향상하는데 목적이 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "Q5.h"
 
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec)
{
    os << "[";
    for (size_t i = 0; i < vec.size(); i++)
    {
        os << vec[i];
        if (i != vec.size() - 1)
        {
            os << ", ";
        }
    }
    os << "]";
    return os;
}
 
cs
 
// main에서 vector 형태로 출력하기위한 기본 셋팅
 

 


5.16 균등하지 않은 임의의 숫자 생성하기

n개의 숫자와 각 숫자의 확률 p0,p1,....p(n-1)이 주어지고, (단 확률의 모든 합은 1)
[0,1]사이의 숫자를 균등하게 생성하는 임의의 숫자 생성기가 주어졌을때, 주어진 확률에 따라 숫자 n개를 생성하시오.


이 문제는 실제로 어떤 숫자가 생성되는지는 중요하지 않다.
n개의 결과를 각각의 확률로 선택하고 싶을 뿐이다. 숫자의 확률이 다르다고 가정하면
[p0, p0 + p1], [p0 + p1, p0 + p1 + p2],  [p0 + p1 + p2 , p0 + p1 + p2 + p3] [p0+... , ...+p(n-1)] 과 같이 구간을 잡고 문제를 풀면 된다.
일반적으로 n개의 구간값이 들어 있는 배열을 탐색하는데 걸리는 시간은 O(n)이다. 하지만 배열이 정렬이 되어있는 형태이므로 이진탐색을 사용하여 O(log n)의 시간복잡도로 나타낼 수 있다.

해당내용의 소스코드와 결과는 다음과 같다.  

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<vector>
#include<random>
#include<numeric>
#include<algorithm>
int NonUniformRandomNumberGeneration(const std::vector<int>& values, 
    const std::vector<double>& probabilities)
{
    std::vector<double> prefix_sums_of_probabilities;
    std::partial_sum(cbegin(probabilities), cend(probabilities),
        back_inserter(prefix_sums_of_probabilities));
 
    std::default_random_engine seed((std::random_device())());
    const double uniform_0_1 = std::generate_canonical<double,
        std::numeric_limits<double>::digits>(seed);
 
    const int interval_idx = std::distance(cbegin(prefix_sums_of_probabilities),
        upper_bound(cbegin(prefix_sums_of_probabilities),
            cend(prefix_sums_of_probabilities), uniform_0_1));
 
    return values[interval_idx];
}
cs
 
// 5.16 균등하지 않은 임의의 숫자 생성하기.cpp
 

 

1
2
3
4
std::vector<int>TestVec14 = { 10,20,30,40,50,60 };
std::vector<double>TestVec15 = { 0.9,0.02,0.02,0.02,0.02,0.02 };
 
std::cout << "5-16 " << NonUniformRandomNumberGeneration(TestVec14, TestVec15) << std::endl//5-16
cs
 
// main.cpp
 

서로 다른 확률 결과