1+ package com .kishan .scala .leetcode .juneChallenges
2+
3+ import scala .util .Random
4+
5+
6+ /*
7+ * Given an array w of positive integers,
8+ * where w[i] describes the weight of index i,
9+ * write a function pickIndex which randomly picks an index in proportion to its weight.
10+ *
11+ */
12+
13+ /*
14+ * Input:
15+ ["Solution","pickIndex"]
16+ [[[1]],[]]
17+ Output: [null,0]
18+ *
19+ * Input:
20+ ["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
21+ [[[1,3]],[],[],[],[],[]]
22+ Output: [null,0,1,1,1,0]
23+ */
24+ */
25+
26+
27+ /*
28+ * Approach:
29+ *
30+ * 1. Calculation Running total for each element of the array.
31+ * 2. Generating a Random number using scala.util.Random (Including upper boundary Value).
32+ * 3. Using Binary Search Algorithm to search the range where the random number is located.
33+ * 4. Finally returning the upper boundary value of the range. Which is the result.
34+ *
35+ * */
36+
37+ /*
38+ * If Input: [8, 9]
39+ *
40+ * Running sum will be [8, 17]
41+ *
42+ * If our Random number lies between 1-8 we will pick the first index.
43+ * If our random number lies between 9-17 we will pick the second index
44+ *
45+ * We will ending up picking the index which has the highest probability
46+ *
47+ * */
48+
49+
50+ class RandomPickWithWeight (_w : Array [Int ]) {
51+
52+ private val length = _w.length
53+ private val totalSum = _w.sum
54+ private val random = new Random ()
55+ private var preSum : Array [Int ] = _w.scan(0 )((a, b) => a + b).drop(1 )
56+
57+ def pickIndex (): Int = {
58+ val randomNumber = random.nextInt(totalSum) + 1
59+ var head = 0
60+ var tail = preSum.length - 1
61+ var mid : Int = head + (tail - head) / 2
62+ while (head < tail) {
63+ mid = head + (tail - mid) / 2
64+ if (randomNumber > preSum(mid)) {
65+ head = mid + 1
66+ } else {
67+ tail = mid
68+ }
69+ }
70+ return if (preSum(tail) >= randomNumber) tail else head
71+ }
72+
73+
74+ }
0 commit comments