开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情
LeetCode398:随机数索引
给你一个可能含有 重复元素 的整数数组 nums ,请你随机输出给定的目标数字 target 的索引。你可以假设给定的数字一定存在于数组中。
实现 Solution 类:
Solution(int[] nums)用数组nums初始化对象。int pick(int target)从nums中选出一个满足nums[i] == target的随机索引i。如果存在多个有效的索引,则每个索引的返回概率应当相等。 示例:
输入
["Solution", "pick", "pick", "pick"]
[[[1, 2, 3, 3, 3]], [3], [1], [3]]
输出
[null, 4, 0, 2]
解释
Solution solution = new Solution([1, 2, 3, 3, 3]);
solution.pick(3); // 随机返回索引 2, 3 或者 4 之一。每个索引的返回概率应该相等。
solution.pick(1); // 返回 0 。因为只有 nums[0] 等于 1 。
solution.pick(3); // 随机返回索引 2, 3 或者 4 之一。每个索引的返回概率应该相等。
提示:
target是nums中的一个整数- 最多调用
pick函数 次
思路分析
根据题意分析:
- 包含重复元素,元素与下标一对多
- 有随机,需要使用随机函数的api
- 需要返回数组下标,不能对原数组排序
- 数组可能很大,考虑减少内存消耗
还有些思考:
- 提前建立hash索引,空间换时间
- 或者查询过程中建立索引,牺牲第一次查询效率,减少内存消耗
算法代码
Random random = new Random();
HashMap < Integer, List < Integer >> map = new HashMap < > ();
public Solution(int[] nums) {
List < Integer > index;
for (int i = 0; i < nums.length; i++) {
if (!map.containsKey(nums[i])) {
index = new ArrayList < > ();
map.put(nums[i], index);
} else {
index = map.get(nums[i]);
}
index.add(i);
}
}
public int pick(int target) {
List < Integer > index = map.get(target);
return index.get(random.nextInt(index.size()));
}
结果详情
算法复杂度
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN)一起进步,一起成长!