LeetCode题练习与总结:随机数索引--398

devtools/2024/11/15 16:39:15/

一、题目描述

给你一个可能含有 重复元素 的整数数组 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 <= 2 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • target 是 nums 中的一个整数
  • 最多调用 pick 函数 10^4 次

二、解题思路

这个问题可以通过水塘抽样(Reservoir Sampling)算法来解决。水塘抽样是一种随机选择算法,用于从n个元素中随机选择k个元素,每个元素被选中的概率相等。

对于这个问题,我们需要从数组 nums 中随机选择一个等于 target 的索引。以下是解题步骤:

  1. 遍历数组 nums,记录目标值 target 出现的次数,以及最后一个出现的位置。
  2. 在遍历过程中,对于每个等于 target 的元素,以 1/i 的概率选择当前索引,其中 i 是当前元素是第几个等于 target 的元素。
  3. 遍历完成后,返回最终选择的索引。

三、具体代码

import java.util.Random;class Solution {private int[] nums;private Random random;public Solution(int[] nums) {this.nums = nums;this.random = new Random();}public int pick(int target) {int count = 0; // 记录target出现的次数int res = 0; // 最终选择的索引for (int i = 0; i < nums.length; i++) {if (nums[i] == target) {count++;// 以1/count的概率选择当前索引if (random.nextInt(count) == 0) {res = i;}}}return res;}
}/*** Your Solution object will be instantiated and called as such:* Solution obj = new Solution(nums);* int param_1 = obj.pick(target);*/

在这个实现中,我们使用了一个 Random 对象来生成随机数。在 pick 方法中,我们遍历数组 nums,每次遇到 target 时,我们计算 random.nextInt(count),如果结果为0,我们就更新 res 为当前的索引 i。这样,每个等于 target 的索引都有相同的概率被选中。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 初始化构造函数 Solution(int[] nums):这个函数只是将输入数组 nums 的引用赋值给类的成员变量,并初始化一个 Random 对象,所以这个操作的时间复杂度是 O(1)。

  • pick(int target) 方法:这个方法中有一个循环,它遍历了整个数组 nums 一次。在循环内部,对于每个元素,我们进行常数时间的操作(比较和随机数生成)。因此,pick 方法的时间复杂度是 O(n),其中 n 是数组 nums 的长度。

综合以上两点,这个类的两个主要操作的时间复杂度如下:

  • 构造函数:O(1)
  • pick 方法:O(n)
2. 空间复杂度
  • 构造函数 Solution(int[] nums):在构造函数中,我们只是存储了输入数组 nums 的引用和一个 Random 对象。由于没有使用额外的数据结构来存储数组 nums 的副本或与数组大小成比例的其他信息,所以构造函数的空间复杂度是 O(1)。

  • pick(int target) 方法:在 pick 方法中,我们使用了两个额外的变量 count 和 res,它们都是整数类型,因此它们的空间占用是常数。这个方法没有使用额外的数据结构,所以它的空间复杂度也是 O(1)。

综合以上两点,这个类的空间复杂度是:

  • 构造函数:O(1)
  • pick 方法:O(1)

因此,整个 Solution 类的空间复杂度是 O(1)。

五、总结知识点

  1. 类定义:代码定义了一个名为 Solution 的类,这是面向对象编程的基本概念。

  2. 成员变量Solution 类中有两个成员变量 nums 和 random,分别用于存储输入的整数数组和一个随机数生成器。

  3. 构造函数Solution 类包含一个构造函数 Solution(int[] nums),用于初始化成员变量。

  4. 方法定义pick(int target) 是一个类方法,用于根据目标值 target 随机选择一个索引。

  5. 数组的遍历:在 pick 方法中,通过一个 for 循环遍历数组 nums

  6. 条件判断:在 for 循环中,使用 if 语句检查当前元素是否等于目标值 target

  7. 计数器:变量 count 用来记录目标值 target 出现的次数。

  8. 随机数生成:使用 Random 类的 nextInt(int bound) 方法生成一个随机数,这个方法生成一个介于 0(包含)和指定值 bound(不包含)之间的随机整数。

  9. 概率选择:通过 if (random.nextInt(count) == 0) 语句,实现了一个概率选择机制,确保每个等于 target 的索引都有相同的概率被选中。

  10. 返回值pick 方法返回一个整数,即随机选择的索引。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。


http://www.ppmy.cn/devtools/134209.html

相关文章

git同步fork和原始仓库

git同步fork和原始仓库 在使用Fork的情况下&#xff0c;保持你的Fork与原始仓库&#xff08;上游仓库&#xff09;同步是一项重要的维护任务&#xff0c;特别是当你想要持续贡献或保持你Fork中的项目更新时。以下是详细的步骤&#xff0c;指导你如何将Fork与上游仓库同步&…

websocket初始化

websocket初始化 前言 上一集我们HTTP的ping操作就可以跑通了&#xff0c;那么我们还有一个协议---websocket&#xff0c;我们在这一集就要去完成我们websocket的初始化。 分析 我们在初始化websocket的之前&#xff0c;我们考虑一下&#xff0c;我们什么时候就要初始化我们…

【NOIP提高组】潜伏者

【NOIP提高组】潜伏者 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; R国和S国正陷入战火之中&#xff0c;双方都互派间谍&#xff0c;潜入对方内部&#xff0c;伺机行动。 历尽艰险后&#xff0c;潜伏于 S 国的R 国间谍小C 终于摸清了S 国…

Spring Boot框架:计算机课程管理的工程认证之桥

3系统分析 3.1可行性分析 通过对本基于工程教育认证的计算机课程管理平台实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于工程教育认证的计算机课程管理平…

蓝桥杯每日真题 - 第13天

题目&#xff1a;&#xff08;删边问题&#xff09; 题目描述&#xff08;14届 C&C B组F题&#xff09; 解题思路&#xff1a; 图的构建&#xff1a;使用邻接链表表示图&#xff0c;边的起点和终点分别存储在数组中&#xff0c;以支持高效的遍历。 Tarjan算法&#xff1a…

Spark 共享变量:广播变量与累加器解析

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…

力扣-Hot100-哈希【算法学习day.30】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

浅谈React的虚拟DOM

React的虚拟DOM&#xff1a;揭秘高效渲染的秘密 在React中&#xff0c;虚拟DOM&#xff08;Virtual DOM&#xff09;是一个核心概念&#xff0c;它是React能够提供高效渲染和更新的关键。虚拟DOM是一个轻量级的JavaScript对象&#xff0c;表示真实的DOM树。通过使用虚拟DOM&am…