For example, if the int[] w ={3,14,1,7}, we can make a presum array based on it: int[] presums = {3, 17, 18, 25}
We using Ramdom's nextInt() to generate a random number:
1. if the number is 1, 2 or 3, return 0;
2.if the number is 4~17, return 1;
3.if the number is 18, return 2;
4.if the number is 19~25 return 3.
We need to notice that the nextInt(25)'s range is 0 ~ 24, so we need to add 1 to the ramdom number, to get 1 ~ 25.
And then we use binary search to search out where the ramdon number should belong to: 1, 2, 3 or 4.
Solution 1:
class Solution { private int[] sums; private Random r=new Random(); private int sum =0; public Solution(int[] w) { sums= new int[w.length]; sums[0]=w[0]; for(int i=1;i<w.length;i++){ sums[i]=sums[i-1]+w[i]; } sum = sums[w.length-1]; } public int pickIndex() { int random = r.nextInt(sum); for(int i=0;i<sums.length;i++){ if(random<sums[i]){ return i; } } return -1; } }
Solution2:
I have used a typical binary search template to do it, just work hard to remember it, that is:
left = 0;
right = length;
if f(mid) == target return target
if f(mid) > target r=mid
if f(mid) < target l = mid+1
return l or r.
class Solution { Random r = new Random(); int sum =0; int[] presums; public Solution(int[] w) { presums = new int[w.length]; for(int i=0;i<w.length;i++){ sum+=w[i]; presums[i]=sum; } } public int pickIndex() { int i = r.nextInt(sum)+1; //the nextInt's range is 0~sum-1, but we need 1~sum return binarySearch(i); } private int binarySearch(int target){ //this binary search is using a typical template int l=0, r=presums.length, mid, res=0; while(l<r){ mid =(l+r)/2; if(presums[mid]==target){ return mid; }else if(presums[mid]>target){ r=mid; }else{ l=mid+1; } } return l; } }
Solution 3:
Using Universal binary search template
class Solution { private int[] sums; private Random r=new Random(); private int sum =0; public Solution(int[] w) { sums= new int[w.length]; sums[0]=w[0]; for(int i=1;i<w.length;i++){ sums[i]=sums[i-1]+w[i]; } sum = sums[w.length-1]; } public int pickIndex() {int random = r.nextInt(sum); int l =0, r = sums.length-1; while(l+1<r){ int mid = (l+r)/2; if(random < sums[mid]){ r=mid; }else{ l=mid; } } if(random < sums[l]) return l; else return r; } }