LeetCode398-随机数索引
原题链接:【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-随机数索引的更多相关文章
- [Swift]LeetCode398. 随机数索引 | Random Pick Index
Given an array of integers with possible duplicates, randomly output the index of a given target num ...
- Java实现 LeetCode 398 随机数索引
398. 随机数索引 给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引. 您可以假设给定的数字一定存在于数组中. 注意: 数组大小可能非常大. 使用太多额外空间的解决方案将不会通过测试 ...
- 398 Random Pick Index 随机数索引
给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引. 您可以假设给定的数字一定存在于数组中.注意:数组大小可能非常大. 使用太多额外空间的解决方案将不会通过测试.示例:int[] num ...
- 产生n不同随机数的算法
昨天无聊,就模仿仙剑5外传中的卡牌游戏做了一个小游戏,结果在开发这个小游戏的时候,碰到了产生多个不同随机数的问题.我们知道,仙剑中的卡牌游戏是随机产生16张图片,并且这16张图片是两个一组的,因为只有 ...
- 求指定范围里的不重复的N个随机数
原本是朋友问了一个题目,怎样把1到25个整形数随机排列,想了想,换个意思就是说如何把25个数随机不重复显示出来,即求1—25中25个随机数的一个数组.最简单的方法即利用双循环,是在每次得到一个随机数后 ...
- leetcode398 and leetcode 382 蓄水池抽样算法
382. 链表随机节点 给定一个单链表,随机选择链表的一个节点,并返回相应的节点值.保证每个节点被选的概率一样. 进阶:如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现? 示 ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- 6月6 Smarty练习----设置题目及打印试卷
所需要的数据库表格:shiti, shititimu, timu, kemu, xuanxiang 考试试题的设置: 考试试题后台:ksset.php <?php include(" ...
- Java基础六(自定义类、ArrayList集合)
今日内容介绍1.自定义类型的定义及使用2.自定义类的内存图3.ArrayList集合的基本功能4.随机点名器案例及库存案例代码优化 ###01引用数据类型_类 * A: 数据类型 * a: java中 ...
随机推荐
- 第K个数 牛客网 程序员面试金典 C++ Python
第K个数 牛客网 程序员面试金典 C++ Python 题目描述 有一些数的素因子只有3.5.7,请设计一个算法,找出其中的第k个数. 给定一个数int k,请返回第k个数.保证k小于等于100. 测 ...
- 一、安装zabbix监控(源码编方式)
首先介绍一下zabbix的运行原理和运行条件. Zabbix监控原理 Zabbix 通过C/S 模式采集数据,通过B/S模式在web 端展示和配置. 被监控端:主机通过安装agent 方式采集数据, ...
- k8s入坑之路(8)kube-proxy详解
kube-proxy 每台机器上都运行一个 kube-proxy 服务,它监听 API server 中 service 和 endpoint 的变化情况,并通过 iptables 等来为服务配置负载 ...
- 攻防世界 WEB 高手进阶区 easytornado Writeup
攻防世界 WEB 高手进阶区 easytornado Writeup 题目介绍 题目考点 Python模板 tornado 模板注入 Writeup 进入题目, 目录遍历得到 /flag.txt /w ...
- Linux 服务器的基本性能及测试方法
1. 摘要 一个基于 Linux 操作系统的服务器运行的同时,也会表征出各种各样参数信息.通常来说运维人员.系统管理员会对这些数据会极为敏感,但是这些参数对于开发者来说也十分重要,尤其当程序非正常工作 ...
- this.$set用法
this.$set()的主要功能是解决改变数据时未驱动视图的改变的问题,也就是实际数据被改变了,但我们看到的页面并没有变化,这里主要讲this.$set()的用法,如果你遇到类似问题可以尝试下,vue ...
- centos7.2安装rabbitmq教程
环境: centos7.2 rabbitmq依赖erlang,需要先安装erlang 1 安装erlang rpm -Uvh https://download.fedoraproject.org/pu ...
- 【开源库推荐】#3 Android EventBus的使用
原文地址:[开源库推荐]#3 Android EventBus的使用 | Stars-One的杂货小窝 EventBus的Github Event bus for Android and Java t ...
- python将字符串转换成对应的python数据类型--eval和json.loads(),json.dumps()
eval()和json.loads() 都可以将字符串转换成对应的python数据类型,举个字典的例子,同样适合其他数据类型元组.列表.集合. In [3]: ss = '{"a" ...
- 力扣 - 剑指 Offer 12. 矩阵中的路径
题目 剑指 Offer 12. 矩阵中的路径 思路1(回溯.DFS) 这题可以使用回溯+递归来解决,思路如下: 将二维数组的每一个元素都作为起点进行回溯查找 每次查找的时候,都有四个方向,但是上一个方 ...