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中 ...
随机推荐
- hdu 1227 Fast Food(DP)
题意: X轴上有N个餐馆.位置分别是D[1]...D[N]. 有K个食物储存点.每一个食物储存点必须和某个餐厅是同一个位置. 计算SUM(Di-(离第i个餐厅最近的储存点位置))的最小值. 1 < ...
- hdu 3032 Nim or not Nim? (SG,然后找规律)
题意: n堆石头,每堆石头个数:s[1]...s[n]. 每人每次可以选择在一堆中取若干个(不能不取),或者把一堆石头分成两堆(两堆要都有石头). 无法操作者负. 数据范围: (1 ≤ N ≤ 10^ ...
- no active checks on server [192.168.1.101:10051]: host [ ] not found
1.查看/etc/zabbix/zabbix_agentd.conf的 hostanme 2.查看zabbix-web中,主机名称 3.将zabbix-web的主机名改成/etc/zabbix/zab ...
- Vulnstack内网靶场4
环境 漏洞详情 (qiyuanxuetang.net) 仅主机模式内网网段192.168.183.0/24 外网网段192.168.157.0/24 其中Ubuntu作为对外的内网机器 攻击机kali ...
- 【Python+postman接口自动化测试】(5)抓包工具Fiddler简介
Fiddler简介 Fiddler 4.6 下载 http://www.downza.cn/soft/234727.html 为什么使用Fiddler? 可以抓到请求数据,查看Raw格式/表单格式/J ...
- centos7.2安装nginx
1 安装相关编译环境 yum install gcc-c++ yum install pcre pcre-devel yum install zlib zlib-level yum openssl o ...
- 在同级路径下,SpringBoot两种类型的配置文件(.properties/.yml)同时存在时,配置优先级如何处理?
两类配置文件如果同时存在,若 key 相同则 properties 优先级高,若key不同则合并加载:
- 【JAVA】笔记(7)--- 数组精讲
数组的静态初始化: 1.一维数组: int [ ] arr = { 1,2,3,4 } ; Object [ ] arr = { new Object ( ) , new Object ( ) , ...
- dart系列之:在dart中使用packages
目录 简介 pubspec.yaml get packages 使用packages 升级依赖 总结 简介 java中使用jar包来封装有用的功能,然后将其分发到maven仓库中,供其他人使用.同样的 ...
- 题解 P6345 [CCO 2017]接雨滴
解题思路 NOIP在即,感觉即将退役,或许是最后一篇题解了... 求水的体积不是特别好求,我们考虑求出 水+柱子 的体积最后再减去柱子的体积. 发现对于最高的柱子在中间的情况其实可以把最高柱子一侧的柱 ...