原题链接:【398. 随机数索引】:https://leetcode-cn.com/problems/random-pick-index/

题目描述:

给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。

注意:

数组大小可能非常大。 使用太多额外空间的解决方案将不会通过测试。

示例:

int[] nums = new int[] {1,2,3,3,3};
Solution solution = new Solution(nums); // pick(3) 应该返回索引 2,3 或者 4。每个索引的返回概率应该相等。
solution.pick(3); // pick(1) 应该返回 0。因为只有nums[0]等于1。
solution.pick(1);

解题思路:

解法1:哈希表。

暴力解法。使用哈希表存储数组中每个元素值到其所有的下标索引的映射。

即key为元素值,value为元素值对应的索引下标列表。

再用random函数,从下标列表中随机选择一个索引返回即可。

这个解法非常占用额外空间O(N),如果数组很大,很容易oom。

解法2:动态数组存储索引列表。

定义一个存储索引下标的索引列表indexList,用动态数组,方便扩展。

遍历数组,如果元素跟target目标值相等,则把索引值添加进indexList列表。

取随机数,rand范围为【0,indexList.length ),然后将对应位置的索引值返回即可。

概率为:1 / indexList.length

这里相比上一种解法,已经降了一个数量级,但是如果N很大,或者数字分布不均匀,indexList也可能非常大,也非常占用额外空间,空间消耗也可能会达到O(N),可能会oom。

解法3:蓄水池抽样算法。

算法是:要从超大数组N中取k个元素,这里是取一个元素,即K=1

那么每次只取一个样本值,那么逐个遍历数组,当遇到第i个数时,就以 1 / i 的概率抽取它做样本值,以(i - 1)/ i 的概率保留原来的样本值,不替换。

我们不需要保存索引下标列表,只需要一个变量cnt计数,统计匹配到了多少个相同的数字,方便后去取随机数,算概率。

遍历数组,如果元素跟target目标值相等,则cnt++,计数器+1。

然后取随机数,rand范围为【1,cnt】。

因为这里只取一个数,就是K=1的案例。

所以如果rand == 1,则取当前元素的下标,替换为结果值。

如果rand > 1,则保留之前的结果,继续往下走。知道结束返回结果值。

特点:这里只需要遍历一遍数组,而且没有额外的空间消耗,只有一个计数器变量cnt。空间复杂度为O(1)。(非常推荐)

题解代码:

代码如下:(java版)

//给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。
//
// 注意:
//数组大小可能非常大。 使用太多额外空间的解决方案将不会通过测试。
//
// 示例:
//
//
//int[] nums = new int[] {1,2,3,3,3};
//Solution solution = new Solution(nums);
//
//// pick(3) 应该返回索引 2,3 或者 4。每个索引的返回概率应该相等。
//solution.pick(3);
//
//// pick(1) 应该返回 0。因为只有nums[0]等于1。
//solution.pick(1);
//
// Related Topics 水塘抽样 哈希表 数学 随机化
// 125 0 import java.util.Random; //leetcode submit region begin(Prohibit modification and deletion)
class Solution { // 需要把nums传递给pick方法,所以我们需要定义一个类变量
int[] nums;
public Solution(int[] nums) {
this.nums = nums;
} public int pick(int target) {
// 定义一个变量,存储结果值
int result = 0;
// 定义一个变量cnt,计数器,标记匹配到了几个相同的数字,方便后面取随机数范围
int cnt = 0;
// 循环遍历链表
for (int i=0; i<nums.length; i++) {
// 匹配跟target元素是否相等
if (nums[i] == target) {
// 匹配到了,则计数器+1
cnt++;
// 取随机数rand范围为[1, cnt],注意这里边界是cnt
int rand = new Random().nextInt(cnt) + 1;
// 取每个数的概率都是 1 / cnt,也就是说有1 / cnt的概率,更新结果下标值
if (rand == 1) {
// rand等于1,则取当前元素的下标,更新结果值
result = i;
}
} } // 返回结果下标
return result;
}
} /**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(nums);
* int param_1 = obj.pick(target);
*/
//leetcode submit region end(Prohibit modification and deletion)

LeetCode398-随机数索引的更多相关文章

  1. [Swift]LeetCode398. 随机数索引 | Random Pick Index

    Given an array of integers with possible duplicates, randomly output the index of a given target num ...

  2. Java实现 LeetCode 398 随机数索引

    398. 随机数索引 给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引. 您可以假设给定的数字一定存在于数组中. 注意: 数组大小可能非常大. 使用太多额外空间的解决方案将不会通过测试 ...

  3. 398 Random Pick Index 随机数索引

    给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引. 您可以假设给定的数字一定存在于数组中.注意:数组大小可能非常大. 使用太多额外空间的解决方案将不会通过测试.示例:int[] num ...

  4. 产生n不同随机数的算法

    昨天无聊,就模仿仙剑5外传中的卡牌游戏做了一个小游戏,结果在开发这个小游戏的时候,碰到了产生多个不同随机数的问题.我们知道,仙剑中的卡牌游戏是随机产生16张图片,并且这16张图片是两个一组的,因为只有 ...

  5. 求指定范围里的不重复的N个随机数

    原本是朋友问了一个题目,怎样把1到25个整形数随机排列,想了想,换个意思就是说如何把25个数随机不重复显示出来,即求1—25中25个随机数的一个数组.最简单的方法即利用双循环,是在每次得到一个随机数后 ...

  6. leetcode398 and leetcode 382 蓄水池抽样算法

    382. 链表随机节点 给定一个单链表,随机选择链表的一个节点,并返回相应的节点值.保证每个节点被选的概率一样. 进阶:如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现? 示 ...

  7. Swift LeetCode 目录 | Catalog

    请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift    说明:题目中含有$符号则为付费题目. 如 ...

  8. 6月6 Smarty练习----设置题目及打印试卷

    所需要的数据库表格:shiti, shititimu, timu, kemu, xuanxiang  考试试题的设置: 考试试题后台:ksset.php <?php include(" ...

  9. Java基础六(自定义类、ArrayList集合)

    今日内容介绍1.自定义类型的定义及使用2.自定义类的内存图3.ArrayList集合的基本功能4.随机点名器案例及库存案例代码优化 ###01引用数据类型_类 * A: 数据类型 * a: java中 ...

随机推荐

  1. lvs 四层负载相关

    都打开 /etc/sysctl.conf 中的 net.ip4.ip_forward=1.开启路由转发功能. 分发器 : eth0:192.168.1.66 (VIP) eth1:192.168.2. ...

  2. 修改linux 两种时间的方法

    1,整理了一下怎么修改linux 两种时间的方法. 硬件时间:hwclock 或者clock,设置的方法是 hwclock --set --date="05/12/2018 12:30:50 ...

  3. openssh 7.4 升级 8.3

    1.删除旧版本(如果是远程连接升级,不能卸载旧版本,否则连接会断开.安装8.3完也不能卸载7.4,否则要到服务器直连重新安装8.3.) # rpm -qa |grep openssh #rpm -e ...

  4. Python Excel工具类封装, 给excel表头搞点颜色

    封装Excel工具类 我们常用的excel工具类,读有xlrd,写有xlwt.有读有写,新一代库有pandas,openpyxl等等. 大家用法都差不多,今天博主就介绍新手最爱,我也爱的xlrd和xl ...

  5. 将python代码转化为c语言代码,提高运行效率

    将python代码转化为c语言代码,提高运行效率 首先,需要安装cpython库: pip install cython 安装完成之后,写一段简单的代码,例如下面这个利用递归求斐波那契数列的函数,然后 ...

  6. Netty数据如何在 pipeline 中流动

    前言 在之前文章中,我们已经了解了pipeline在netty中所处的角色,像是一条流水线,控制着字节流的读写,本文,我们在这个基础上继续深挖pipeline在事件传播 Unsafe对象 顾名思义,u ...

  7. 力扣 - 剑指 Offer 42. 连续子数组的最大和

    题目 剑指 Offer 42. 连续子数组的最大和 思路1(分析数组的规律) 我们可以从头到尾逐个累加,若之前的累加和小于0,那就从丢弃之前的累加,从当前开始重新累加,同时在遍历过程中比较记录下最大值 ...

  8. 虚拟机Centos7安装Socks5作为代理服务器

    虚拟机Centos7安装Socks5作为代理服务器 1. 什么是代理服务器 代理服务器(Proxy Server)是一种重要的服务器安全功能,它的工作主要在开放系统互联(OSI)模型的会话层,从而起到 ...

  9. KNN算法实现对iris数据集的预测

    KNN算法的实现 import pandas as pd from math import dist k = int(input("请输入k值:")) dataTest = pd. ...

  10. 群晖ping自动关机

    因为学校宿舍环境的原因,每天早上10点左右宿管可能会来检查内务情况,然后一定会关闭电闸,就导致如果我的nas在10点半时开机的话用的是UPS的电源,直接导致UPS电量耗竭,而我又不可能一直去观察宿舍有 ...