1. 程式人生 > >[Swift]LeetCode528. 按權重隨機選擇 | Random Pick with Weight

[Swift]LeetCode528. 按權重隨機選擇 | Random Pick with Weight

pic 輸入 let 隨機 超過 earch with nts ons

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.

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]

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 ,它可以隨機地獲取位置 i,選取位置 i 的概率與 w[i] 成正比。

說明:

  1. 1 <= w.length <= 10000
  2. 1 <= w[i] <= 10^5
  3. pickIndex 將被調用不超過 10000

示例1:

輸入: 
["Solution","pickIndex"]
[[[1]],[]]
輸出: [null,0]

示例2:

輸入: 
["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
[[[1,3]],[],[],[],[],[]]
輸出: [null,0,1,1,1,0]

輸入語法說明:

輸入是兩個列表:調用成員函數名和調用的參數。Solution 的構造函數有一個參數,即數組 wpickIndex 沒有參數。輸入參數是一個列表,即使參數為空,也會輸入一個 [] 空列表。


704ms

 1 class Solution {
 2     var total: Int
 3     var pTotal: [Int]
 4     init(_ w: [Int]) {
 5         total = 0
 6         pTotal = [Int]()
 7         for x in w{
 8             total += x
 9             pTotal.append(total)
10         }
11     }
12     
13     func pickIndex() -> Int {
14         let index = Int.random(in: 0..<total)
15         var lo = 0, hi = pTotal.count-1
16         while lo != hi{
17             let mid = (lo+hi)/2
18             if pTotal[mid] <= index{
19                 lo = mid + 1
20             }else{
21                 hi = mid
22             }
23         }
24         return lo
25     }
26 }
27 
28 /**
29  * Your Solution object will be instantiated and called as such:
30  * let obj = Solution(w)
31  * let ret_1: Int = obj.pickIndex()
32  */

720ms

 1 class Solution {
 2 
 3     let nums:[Int]
 4     
 5     init(_ w: [Int]) {
 6         var sum = 0
 7         var result = [Int]()
 8         w.forEach {
 9             sum += $0
10             result.append(sum)
11         }
12         nums = result
13     }
14     
15     func pickIndex() -> Int {
16        let sum = nums.last!
17        let num = Int.random(in: 0..<sum) % sum
18         var left = 0
19         var right = nums.count - 1
20         while left + 1 < right {
21             let mid = left + (right - left) / 2
22             if nums[mid] > num {
23                 right = mid
24             } else {
25                 left = mid
26             }
27         }
28         
29         if nums[left] > num {
30             return left
31         } else {
32             return right
33         }
34     }
35 }

752ms

 1 class Solution {
 2     
 3     let w: [Int]
 4     let sum: Int
 5 
 6     init(_ w: [Int]) {
 7         sum = w.reduce(0, +)
 8         self.w = w.reduce([Int]()){ 
 9             let n = ($0.last ?? 0) + $1
10             return $0 + [n]
11         }
12     }
13     
14     func pickIndex() -> Int {
15         let random = Int.random(in: 0...sum-1)
16         return searchInsert(w, random)
17     }
18     
19     func searchInsert(_ nums: [Int], _ target: Int) -> Int {
20         var low = 0
21         var high = nums.count-1
22         while low <= high {
23             let middle = (low + high) / 2
24             if nums[middle] == target {
25                 return middle+1
26             } else if nums[middle] > target {
27                 high = middle - 1
28             } else {
29                 low = middle + 1
30             }
31         }
32         return low
33     }
34 }

772ms

 1 class Solution {
 2     
 3     var sum: [Int]
 4 
 5     init(_ w: [Int]) {
 6         sum = [Int]()
 7         sum.append(w[0])
 8         for i in 1..<w.count {
 9             sum.append(sum[i-1] + w[i])
10         }
11     }
12     
13     func pickIndex() -> Int {
14         let value = Int.random(in: 1...sum.last!)
15         return bSearch(value, 0, sum.count - 1)
16     }
17     
18     private func bSearch(_ value: Int, _ start: Int, _ end: Int) -> Int {
19         let mid = start + (end - start) / 2
20         if sum[mid] >= value && (start == mid || sum[mid - 1] < value) { return mid }
21         if sum[mid] < value {
22             return bSearch(value, mid + 1, end)
23         }
24         return bSearch(value, start, mid - 1)
25     }
26 }

784ms

 1 class Solution {
 2 
 3     private let accSum: [Int]
 4 
 5     init(_ w: [Int]) {
 6         self.accSum = w.reduce([]) { $0 + [($0.last ?? 0) + $1]}
 7     }
 8     
 9     func pickIndex() -> Int {
10         let num = Int.random(in: 1 ... accSum.last!)  
11         var (left, right) = (0, accSum.count - 1)
12         while left < right {
13             let mid = left + (right - left) / 2
14             if accSum[mid] == num {
15                 return mid
16             } else if accSum[mid] < num {
17                 left = mid + 1
18             } else {
19                 right = mid
20             }
21         }
22 
23         return left
24     }
25 }

Runtime: 976 ms Memory Usage: 19.9 MB
 1 class Solution {
 2     var sum:[Int]
 3 
 4     init(_ w: [Int]) {
 5         sum = w
 6         for i in 1..<w.count
 7         {
 8             sum[i] += sum[i - 1]
 9         }        
10     }
11     
12     func pickIndex() -> Int {
13         var x:Int = Int.random(in:0..<sum.last!)
14         var left:Int = 0
15         var right:Int = sum.count - 1  
16         var mid:Int = 0
17         while (left < right)
18         {
19             mid = left + (right - left) / 2
20             if sum[mid] <= x
21             {
22                 left = mid + 1
23             }
24             else 
25             {
26                 right = mid
27             }            
28         }        
29         return right   
30     }
31 }
32 
33 /**
34  * Your Solution object will be instantiated and called as such:
35  * let obj = Solution(w)
36  * let ret_1: Int = obj.pickIndex()
37  */
38  

[Swift]LeetCode528. 按權重隨機選擇 | Random Pick with Weight