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中 ...
随机推荐
- JAVA笔记7__接口应用/Object类/简单工厂模式/静态代理模式/适配器模式
/** * 接口应用 */ public class Main { public static void main(String[] args) { Person p = new Person(&qu ...
- Python3使用Print输出彩色字体
一.介绍 在一些开发程序中,有些输出消息需要突出显示,我们可以尝试着给他们换上更靓丽的颜色来突出显示. 二.实现过程 终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关. ...
- loto仪器_如何模拟输出凸轮轴和曲轴波形_用任意波形信号源SIG852?
loto仪器_如何模拟输出凸轮轴和曲轴波形_用任意波形信号源SIG852? 在汽车传感器的波形检测应用中,有时候需要模拟各种汽车传感器的输出信号,用来驱动和监测对应的执行机构或者电路是否正常,这其中, ...
- AliRTC 开启视频互动 “零计算” 时代
在 2021 云栖大会<产业视频化创新与最佳实践>视频云主题论坛中,阿里云智能高级技术专家在<AliRTC 开启视频互动 "零处理" 时代>的主题演讲中,发 ...
- Spark的安装及其配置
1.Spark下载 https://archive.apache.org/dist/spark/ 2.上传解压,配置环境变量 配置bin目录 解压:tar -zxvf spark-2.4.5-bin- ...
- 【Java】 List和Array转换
List转Array toArray 首先展示初学者容易犯的错误示例 List<String> strList = new ArrayList<>(); strList.add ...
- PTA 7-1 是否完全二叉搜索树 (30分)
PTA 7-1 是否完全二叉搜索树 (30分) 将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果. ...
- LINKERD 2.11 中文实战手册
1. 将您的服务添加到 Linkerd. 为了让您的服务利用 Linkerd,它们还需要通过将 Linkerd 的数据平面代理注入到它们的 pod 中来进行 网格化 . 2. 自动化的金丝雀发布. 通 ...
- [loj2504]小H爱染色
以下考虑直接对所有$F(A)$求和,并给出两种做法-- 做法1: 枚举答案$A$,对应方案数为${n-A\choose m}^{2}-{n-A-1\choose m}^{2}$,即答案为$\sum_{ ...
- [nowcoder5667G]Greater and Greater
令$f[i][j]$表示前i个数的后j位能否匹配b的前j位,有转移$f[i][j]=f[i-1][j-1] \ \&\ [b_{j}\le a_{i}]$ 将$g[i][j]=[b_{j}\ ...