Try   HackMD

【LeetCode】 528. Random Pick with Weight

Description

Given an array w of positive integers, where w[i] describes the weight of index i, write a function pickIndex which randomly picks an index in proportion to its weight.

Note:

  1. 1 <= w.length <= 10000
  2. 1 <= w[i] <= 10^5
  3. pickIndex will be called at most 10000 times.

Explanation of Input Syntax:
The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array w. pickIndex has no arguments. Arguments are always wrapped with a list, even if there aren't any.

給予一正整數陣列w,其中w[i]描述索引為i的權重。寫一個函式pickIndex會按照權重去隨機挑選一個索引。

注意:

  1. 1 <= w.length <= 10000
  2. 1 <= w[i] <= 10^5
  3. pickIndex 至少會被呼叫 10000 次。

輸入語法解釋:
輸入會是兩個列表:哪些副程式被呼叫和它們的參數。
Solution的建構子有一個參數:陣列wpickIndex沒有參數。參數總是被包裝在列表中,即便沒有任何參數。

Example:

Example 1:

Input: 
["Solution","pickIndex"]
[[[1]],[]]
Output: [null,0]


Example 2:

Input: 
["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
[[[1,3]],[],[],[],[],[]]
Output: [null,0,1,1,1,0]

Solution

  • 使用rand()可以得到一個隨機值,介於0到int的最大值。
  • 給予權重時,使用另一個vector去儲存它;並將元素改為遞增。
    • 如果權重為[1, 2, 3],新的vector[1, 3, 6]
  • 接著我們將rand() % sum(w),可以得到一個0 ~ sum(w)的數字。
  • 最後去找這個隨機數落在vector的哪個區間,就代表選到哪個數字。
    • 權重越大的索引,對應到的區間也越大,所以越容易被選中,藉此達到權重隨機。
  • 下方code中,search的部分使用線性搜尋,可改用二分搜尋來加速。

Code

class Solution { public: Solution(vector<int>& w) { int sum = 0; for(int i = 0; i < w.size(); i++) { sum += w[i]; this->w.push_back(sum); } } int pickIndex() { int r = rand() % w.back(); for(int i = 0; i < w.size(); i++) if(r < w[i]) return i; return w.size() - 1; } private: vector<int> w; }; /** * Your Solution object will be instantiated and called as such: * Solution* obj = new Solution(w); * int param_1 = obj->pickIndex(); */
tags: LeetCode C++