算法初探LeetCode-随机数索引

55 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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 之一。每个索引的返回概率应该相等。

提示:

  • 1<=nums.length<=21041 <= nums.length <= 2 * 10^4
  • 231<=nums[i]<=2311-2^{31} <= nums[i] <= 2^{31} - 1
  • target 是 nums 中的一个整数
  • 最多调用 pick 函数 10410^4 次

思路分析

根据题意分析:

  • 包含重复元素,元素与下标一对多
  • 有随机,需要使用随机函数的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()));
}

结果详情

Snipaste_2023-02-25_22-04-08.png

算法复杂度

  • 空间复杂度:O(n)O(n)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!