528. Random Pick with Weight - Medium
前往題目
想法
- 題目要求每次
pickIndex
的時候都根據機率return
數值,例如[1,3]
那return 1
的機率就是$1 / (1 + 3)$,return 3
的機率是$3 / (1 + 3)$ - 但是讓我困惑的是要怎麼根據機率return。算機率很簡單,只要弄個hashmap把每個機率存下來就好了;或是存sum,然後直接算也很快
思路
這題很妙…解法也有些不懂的地方
大致上就是把每個數字之間的區間拉成他們的數字比例,例如123
會變成136
,這樣1~3
之間就有2
,3~6
之間就有3
,也就是說彼此之間的距離就是原本的數字,因為根據題目的公式,數字越大代表權重大被選到的機率也就越大
- 紀錄每個
index
的prefix sum
- 選定一個隨機數,
Binary search
直到找到最接近隨機數的數字(但是要大於隨機數,如果等於那就直接是答案了)
這個演算法用想的實在是很反直覺,跟一般binary search
有一點點的差異,r = mid
而不是mid - 1
因為mid
有可能是答案,而且最後是回傳l
而不是mid
,但如果多加一句if (randNum == prefixSum[mid]) return mid
其實也是accept
的
Code
class Solution {
private int total; // total sum of w[]
private int[] prefixSum; // Prefix sum of every index
public Solution(int[] w) {
total = 0;
prefixSum = new int[w.length];
int tempTotal = 0;
// Calculate prefixsum
for (int i = 0; i < w.length; ++i) {
tempTotal += w[i];
prefixSum[i] = tempTotal;
}
total = tempTotal;
}
public int pickIndex() {
// The random number
int randNum = new Random().nextInt(total) + 1;
// left and right pointer
int l = 0, r = prefixSum.length - 1;
int mid = 0;
// The answer found when they meet
while (l < r) {
mid = l + (r - l) / 2;
if (randNum > prefixSum[mid]){
l = mid + 1;
} else {
r = mid; // Since mid might be the answer
}
}
// Return left pointer
return l;
}
}
2024/05/07
- 權重
random
不知道怎麼弄,原來是要利用prefixSum
528. Random Pick with Weight - Medium
https://f88083.github.io/2024/01/04/528-Random-Pick-with-Weight-Medium/