题目
Given an array of integers with possible duplicates, randomly output the index of a given target number. You can assume that the given target number must exist in the array.
Note:
The array size can be very large. Solution that uses too much extra space will not pass the judge.
Example:
int[] nums = new int[] {1,2,3,3,3};
Solution solution = new Solution(nums);
// pick(3) should return either index 2, 3, or 4 randomly. Each index should have equal probability of returning.
solution.pick(3);
// pick(1) should return 0. Since in the array only nums[0] is equal to 1.
solution.pick(1);
中文大意
给定一个数组,在数组中寻找指定的元素target,如果多个位置上的元素值为target,那么程序以相同的概率输出每个位置信息。如果在数组中不存在target,输出的结果为-1。
分析
找到数组中指定元素的位置并不难,但是如何能够等概率地随机输出每个位置信息?
(1)随机性,我们可以采用随机数的方式(Random类的使用),保证输出结果的随机性。
(2)等概率性,可以先获得target对应值的所有下标位置,然后从这些位置中随机算出一个位置,即可保证等概率性。
java代码实现一
class Solution {
private int[] nums;
private Random r;
public Solution(int[] nums) {
this.nums = nums;
this.r = new Random();
}
public int pick(int target) {
List<Integer> templist = new ArrayList<Integer>();
int res = -1;
for(int i = 0;i <nums.length;i++){
if(nums[i] == target){
templist.add(i);
}
}
return res = templist.size()==0 ? res : templist.get(r.nextInt(templist.size()));
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(nums);
* int param_1 = obj.pick(target);
*/
java代码实现二
class Solution {
private int[] nums;
private Random r;
public Solution(int[] nums) {
this.nums = nums;
this.r = new Random();
}
public int pick(int target) {
int len = nums.length;
int count = 0;
int res = -1;
for(int i = 0; i<len; i++){
if(nums[i] == target){
if(r.nextInt(++count) == 0){
res = i;
}
}
}
return res;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(nums);
* int param_1 = obj.pick(target);
*/
知识点补充:随机数的生成
生成随机数有两种方法:
方法一:使用Random类
(1)Random类位于java.util包中;
(2)Random的实例能生成一系列伪随机数。
(3)具体实现:
Random r - new Random();
int res = r.nextInt(num);//随机数的区间为[0,num)
类似的方法:nextBytes(byte[] bytes)、nextInt()、nextLong()、nextBoolean()、nextFloat()、nextDouble()
方法二:使用Math工具类
(1)Math类位于java.lang包中;
(2)Math.random()方法生成double型正随机数,随机数的区间为[0.0,1.0);
(3)具体实现:
double res = Math.random();
int resint = (int)res;