Leetcode528按權(quán)重隨機(jī)選擇解題思路

前言

按權(quán)重隨機(jī)選擇在開發(fā)中是一個(gè)相對(duì)于其他leetcode題來說比較實(shí)用,且在日常開發(fā)中會(huì)見到和使用的算法橄登,還是有現(xiàn)實(shí)場(chǎng)景應(yīng)用的沐祷。所以今天leetcode每日刷題AC后脚仔,覺得還是有必要做個(gè)筆記總結(jié)下歹河。

Leetcode 528.按權(quán)重隨機(jī)選擇

給定一個(gè)正整數(shù)數(shù)組 w 齿椅,其中 w[i] 代表下標(biāo) i 的權(quán)重(下標(biāo)從 0 開始),請(qǐng)寫一個(gè)函數(shù) pickIndex 启泣,它可以隨機(jī)地獲取下標(biāo) i,選取下標(biāo) i 的概率與 w[i] 成正比示辈。

例如寥茫,對(duì)于 w = [1, 3],挑選下標(biāo) 0 的概率為 1 / (1 + 3) = 0.25 (即矾麻,25%)纱耻,而選取下標(biāo) 1 的概率為 3 / (1 + 3) = 0.75(即,75%)险耀。

也就是說弄喘,選取下標(biāo) i 的概率為 w[i] / sum(w) 。

示例 1:

輸入:
["Solution","pickIndex"]
[[[1]],[]]

輸出:
[null,0]

解釋:
Solution solution = new Solution([1]);
solution.pickIndex(); // 返回 0甩牺,因?yàn)閿?shù)組中只有一個(gè)元素蘑志,所以唯一的選擇是返回下標(biāo) 0。

  • 1 <= w.length <= 10000
  • 1 <= w[i] <= 10^5
  • pickIndex 將被調(diào)用不超過 10000

讀題:

  1. w[i] 代表下標(biāo) i 的權(quán)重贬派。

  2. 選下標(biāo) i 的概率為 w[i] / sum(w)急但,即此權(quán)重值除以整個(gè)數(shù)組的累加和。

要求:寫個(gè)函數(shù)pickIndex搞乏,使能夠隨機(jī)獲得下標(biāo) i 波桩,選取下標(biāo) i 的概率與 w[i] 成正比。

場(chǎng)景例子

比如:假如有10個(gè)游戲道具请敦,有屠龍寶刀镐躲,也有燒火棍等等。需要隨機(jī)抽出一個(gè)發(fā)給玩家侍筛。由于道具的稀缺度萤皂,價(jià)值等不同,所以抽取的概率肯定不希望是是平均的勾笆。也就是高價(jià)值高權(quán)重獲得的概率低敌蚜,低價(jià)值低權(quán)重獲得的概率高。

要實(shí)現(xiàn)這種效果窝爪,就需要給每個(gè)道具指定一個(gè)權(quán)重弛车。比如燒火棍比較垃圾給個(gè)權(quán)重80齐媒,屠龍寶刀稀有給個(gè)權(quán)重20。即80%的概率會(huì)抽到燒火棍纷跛,這個(gè)就是基于權(quán)重的隨機(jī)算法喻括。

本題意思相對(duì)比較簡(jiǎn)單,與上邊的場(chǎng)景例子期望相反贫奠。期望對(duì)數(shù)組的元素隨機(jī)采樣唬血,元素的權(quán)重比越高,出現(xiàn)的概率越高唤崭。

解題

以 w = [1, 2, 4, 3]為例:

sum 是10拷恨。相當(dāng)于有10個(gè)矩形格子。按照1谢肾、2腕侄、4、3來劃分4個(gè)區(qū)間芦疏。

我們?cè)谶@10之內(nèi)隨機(jī)取一個(gè)數(shù)冕杠。

  • 例如1,落在了第1個(gè)區(qū)間酸茴,對(duì)應(yīng)的index就是0分预。
  • 例如2,落在了第2個(gè)區(qū)間薪捍,對(duì)應(yīng)的index就是1笼痹。
  • 例如3,落在了第2個(gè)區(qū)間酪穿,對(duì)應(yīng)的index就是1与倡。
  • 例如4,落在了第3個(gè)區(qū)間昆稿,對(duì)應(yīng)的index就是2纺座。
  • 例如5,落在了第3個(gè)區(qū)間溉潭,對(duì)應(yīng)的index就是2净响。
  • 例如6,落在了第3個(gè)區(qū)間喳瓣,對(duì)應(yīng)的index就是2馋贤。
  • 例如7,落在了第3個(gè)區(qū)間畏陕,對(duì)應(yīng)的index就是2配乓。
  • 例如8,落在了第4個(gè)區(qū)間,對(duì)應(yīng)的index就是3犹芹。
    .
    .


    截屏2021-08-30 上午1.48.57.png

其實(shí)說白了崎页,原本每一個(gè)數(shù)的初始概率都為1 / 10,w 數(shù)組內(nèi)某個(gè)元素的值越大腰埂,權(quán)重越大飒焦,你期望它被選中的概率越大,那么這個(gè)值對(duì)應(yīng)的區(qū)間范圍就要越大屿笼。

所以就像 w[2] = 4牺荠,我們就讓它占據(jù)4個(gè)格子,那它占用的格子數(shù)是最多了驴一,被選中的概率就最大了休雌。

代碼

個(gè)人題解:

class Solution {
public:
    Solution(vector<int>& w) {
        preSum = w;
        int size = w.size();
        for (int i = 1; i < size; i++) {
            preSum[i] += preSum[i - 1];
        }
    }
    
    int pickIndex() {
        int p = rand() % preSum.back() + 1;
        return lower_bound(preSum.begin(), preSum.end(), p) - preSum.begin();
    } 
private:
    vector<int> preSum;
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(w);
 * int param_1 = obj->pickIndex();
 */

官方題解:

class Solution {
private:
    mt19937 gen;
    uniform_int_distribution<int> dis;
    vector<int> pre;

public:
    Solution(vector<int>& w): gen(random_device{}()), dis(1, accumulate(w.begin(), w.end(), 0)) {
        partial_sum(w.begin(), w.end(), back_inserter(pre));
    }
    
    int pickIndex() {
        int x = dis(gen);
        return lower_bound(pre.begin(), pre.end(), x) - pre.begin();
    }
};

時(shí)間復(fù)雜度:

  1. Solution時(shí)間復(fù)雜度為 O(n)
  2. pickIndex里的lower_bound原理是二分查找,時(shí)間復(fù)雜度為 O(logn)

空間復(fù)雜度:O(n)

拓展

概率加權(quán)的隨機(jī)抽樣 (Weighted Random Sampling) – A-Res 蓄水池算法

其他算法詳細(xì)題解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肝断,一起剝皮案震驚了整個(gè)濱河市挑辆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孝情,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洒嗤,死亡現(xiàn)場(chǎng)離奇詭異箫荡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)渔隶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門羔挡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人间唉,你說我怎么就攤上這事绞灼。” “怎么了呈野?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵低矮,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我被冒,道長(zhǎng)军掂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任昨悼,我火速辦了婚禮蝗锥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘率触。我一直安慰自己终议,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著穴张,像睡著了一般细燎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陆馁,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天找颓,我揣著相機(jī)與錄音,去河邊找鬼叮贩。 笑死击狮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的益老。 我是一名探鬼主播彪蓬,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼捺萌!你這毒婦竟也來了档冬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤桃纯,失蹤者是張志新(化名)和其女友劉穎酷誓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體态坦,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盐数,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伞梯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玫氢。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谜诫,靈堂內(nèi)的尸體忽然破棺而出漾峡,到底是詐尸還是另有隱情,我是刑警寧澤喻旷,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布生逸,位于F島的核電站,受9級(jí)特大地震影響且预,放射性物質(zhì)發(fā)生泄漏牺陶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一辣之、第九天 我趴在偏房一處隱蔽的房頂上張望掰伸。 院中可真熱鬧,春花似錦怀估、人聲如沸狮鸭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歧蕉。三九已至灾部,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惯退,已是汗流浹背赌髓。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留催跪,地道東北人锁蠕。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像懊蒸,于是被迫代替她去往敵國(guó)和親荣倾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容