一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
今天是周二了,距离放假还有4天,加油!
随机数索引
该题出自力扣的398题 —— 随机数索引【中等题】
审题
给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。
注意:
数组大小可能非常大。 使用太多额外空间的解决方案将不会通过测试
-
这题的题意并没有很复杂,就是给出一个数组,里面可能含重复元素,需要实现一个方法——返回该元素出现的随机下标
-
初看题意可能会被吓到,数组大小可能非常大,但是如果转换成英文翻译其实也还好
1 <= nums.length <= 2 * 104
-
因为需要记录下标,和下标对应的值,所以这边会考虑使用Map,key为值,value为List存储出现的下标位置
-
并且题意需要返回一个值的对应下标,且要随机的下标,所以使用Random
-
解法一: Map + Random
- 函数的初期定义出Map和Random
- 构造函数内遍历数组
- 如果map内对应的值没有列表,则创建,否则对列表add下标
- 并且覆盖map
- 返回方法:获取map对应值的列表,返回列表内的随机下标
-
时间复杂度为O(n),因为需要在构造方法内遍历数组
-
空间复杂度O(n),需要开辟Map的空间去存储数组
-
其实并不止这一种解法,还有一种解法去降低空间复制度
- 构造方法不需要额外开辟空间
- 输出随机下标的方法:
- 遍历数组,如果遇到目标返回值时,随机数如果 == 0,则代表概率与等于目标值一样,则记录下标
- 只到最后一次覆盖下标时则返回
编码
class Solution {
Random random = new Random();
HashMap<Integer, List<Integer>> map = new HashMap<>();
public Solution(int[] nums) {
for (int i = 0;i<nums.length;i++) {
List<Integer> list = map.getOrDefault(nums[i], new ArrayList<>());
list.add(i);
map.put(nums[i], list);
}
}
public int pick(int target) {
List<Integer> list = map.get(target);
return list.get(random.nextInt(list.size()));
}
}