算法小知识-----04.26-----随机数索引

106 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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()));
    }
}


image.png