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);
요런 방법을 생각할 수 있겠으나
class Solution {
private HashMap<Integer, List<Integer>> indices;
private Random rand;
public Solution(int[] nums) {
this.rand = new Random();
this.indices = new HashMap<Integer, List<Integer>>();
int l = nums.length;
for (int i = 0; i < l; ++i) {
if (!this.indices.containsKey(nums[i])) {
this.indices.put(nums[i], new ArrayList<>());
}
this.indices.get(nums[i]).add(i);
}
}
public int pick(int target) {
int l = indices.get(target).size();
// pick an index at random
int randomIndex = indices.get(target).get(rand.nextInt(l));
return randomIndex;
}
}
요고
class Solution {
private int[] nums;
private Random rand;
public Solution(int[] nums) {
this.nums = nums;
this.rand = new Random();
}
public int pick(int target) {
int n = this.nums.length;
int count = 0;
int idx = 0;
for (int i = 0; i < n; ++i) {
// if nums[i] is equal to target, i is a potential candidate
// which needs to be chosen uniformly at random
if (this.nums[i] == target) {
// increment the count of total candidates
// available to be chosen uniformly at random
count++;
// we pick the current number with probability 1 / count (reservoir sampling)
if (rand.nextInt(count) == 0) {
idx = i;
}
}
}
return idx;
}
}