JavaC++题解与拓展——leetcode398.随机数索引【水塘抽样学习】
每日一题做题记录,参考官方和三叶的题解 |
文章目录
- 题目要求
- 思路一:模拟、哈希表
- Java
- C++
- 思路二:水塘抽样(蓄水池抽样)
- Java
- C++
- 总结
题目要求
思路一:模拟、哈希表
把数组内容整理一下放哈希表,然后从哈希表取值随机返回。
哈希表存的内容是数组元素和它对应的所有下标。
Java
class Solution {Map<Integer, List<Integer>> map;Random ran;public Solution(int[] nums) {map = new HashMap<Integer, List<Integer>>();ran = new Random();for(int i = 0; i < nums.length; ++i) {map.putIfAbsent(nums[i], new ArrayList<Integer>()); // 相同元素放一起map.get(nums[i]).add(i); // 存下标}}public int pick(int target) {List<Integer>idx = map.get(target); // 取下标return idx.get(ran.nextInt(idx.size()));}
}
- 时间复杂度:初始化为O(n)O(n)O(n),pick函数为O(1)O(1)O(1)
- 空间复杂度:O(n)O(n)O(n)
C++
class Solution {unordered_map<int, vector<int>> map;
public:Solution(vector<int>& nums) {for(int i = 0; i < nums.size(); ++i)map[nums[i]].push_back(i); // 相同元素下标放一起}int pick(int target) {auto &idx = map[target]; // 取下标return idx[rand() % idx.size()];}
};
- 时间复杂度:初始化为O(n)O(n)O(n),pick函数为O(1)O(1)O(1)
- 空间复杂度:O(n)O(n)O(n)
思路二:水塘抽样(蓄水池抽样)
降低空间复杂度,边读边取,适用于长长长文件读取处理。
- 遍历numsnumsnums,每次遇到targettargettarget元素都选择性更新结果。
- 设当前为第cntcntcnt次,选择方法为产生[0,cnt)[0,cnt)[0,cnt)内的一个随机整数ranranran:
- 若ran=0ran=0ran=0,更新结果为当前元素在数组中的下标(不是cntcntcnt);
- 若ran≠0ran\ne 0ran=0:不更新结果。
这个选择方法是怎么保证返回每个下标概率相同的呢?
P(第i个target元素下标成为结果)\quad P(第i个target元素下标成为结果)P(第i个target元素下标成为结果)
P(rani=0)×P(rani+1≠0)×⋯×P(rank≠0)\quad P(ran_i=0)\times P(ran_{i+1}\ne 0)\times \dots\times P(ran_k\ne 0)P(rani=0)×P(rani+1=0)×⋯×P(rank=0)
=1i×(1−1i+1)×⋯×(1−1k)=\frac{1}{i}\times(1-\frac{1}{i+1})\times\dots\times(1-\frac{1}{k})=i1×(1−i+11)×⋯×(1−k1)
=1i×ii+1×⋯×k−1k=\frac{1}{i}\times\frac{i}{i+1}\times\dots\times\frac{k-1}{k}=i1×i+1i×⋯×kk−1
=1k=\frac{1}{k}=k1
注:raniran_irani指第iii轮中选择的随机数。
Java
class Solution {int[] nums;Random ran;public Solution(int[] nums) {this.nums = nums;ran = new Random();}public int pick(int target) {int res = 0;for(int i = 0, cnt = 0; i < nums.length; ++i) {if(nums[i] == target) {++cnt; // 第cnt个targetif(ran.nextInt(cnt) == 0)res = i;}}return res;}
}
- 时间复杂度:初始化为O(1)O(1)O(1),pick函数为O(n)O(n)O(n)
- 空间复杂度:O(1)O(1)O(1)
C++
class Solution {vector<int> &nums;
public:Solution(vector<int>& nums) : nums(nums) {}int pick(int target) {int res;for(int i = 0, cnt = 0; i < nums.size(); ++i) {if(nums[i] == target) {++cnt; // 第cnt个targetif(rand() % cnt == 0)res = i;}}return res;}
};
- 时间复杂度:初始化为O(1)O(1)O(1),pick函数为O(n)O(n)O(n)
- 空间复杂度:O(1)O(1)O(1)
总结
快乐题目+1,学了新的抽样方法,可以用来处理不定长的巨大数据流,还能保证对每个数的抽取概率一致。
欢迎指正与讨论! |
JavaC++题解与拓展——leetcode398.随机数索引【水塘抽样学习】相关推荐
- JavaC++题解与拓展——leetcode728.自除数【跳出多层循环,vector at】
每日一题做题记录,参考官方和三叶的题解 目录 题目要求 思路一:模拟 Java out C++ Python3 思路二:二分 Java C++ vector 思路三:哈希表 Java C++ 总结 题 ...
- JavaC++题解与拓展——leetcode1823.找出游戏的获胜者【约瑟夫环】
每日一题做题记录,参考官方和三叶的题解 目录 题目要求 思路一:模拟 Java C++ 思路二:递归 Java C++ 思路三:迭代 Java C++ Rust 总结 题目要求 [这个问题似乎叫做约瑟 ...
- JavaC++题解与拓展——leetcode310.最小高度树【复习链式前向星】
每日一题做题记录,参考官方和三叶的题解 目录 题目要求 思路一:动态规划 Java 链式前向星 C++ 思路二:拓扑排序+BFS Java C++ 总结 题目要求 思路一:动态规划 遍历整个图,当前遍 ...
- JavaC++题解与拓展——leetcode812.最大三角形面积【么的新知识】
每日一题做题记录,参考官方和三叶的题解 目录 题目要求 思路:枚举 Java C++ Rust 总结 题目要求 思路:枚举 兜兜转转考虑了一圈,结果发现是暴力模拟-- Java class Solut ...
- leetcode刷题记录-398. 随机数索引
前言 今天的题目为中等,跟之前碰到过的一道题思路很相似,利用map表来空间换时间,以此来做到节省时间复杂度. 每日一题 今天的题目是 398. 随机数索引,难度为中等 给你一个可能含有 重复元素 的整 ...
- 【PATB1041】考试座位号(题解+拓展)
[PATB1041]考试座位号(题解+拓展) 原题 题目 输入格式 输出格式 输入样例 输出样例 代码及思路 拓展(通过准考证号找另两个号) 原题 题目 每个 PAT 考生在参加考试时都会被分配两个座 ...
- 398. 随机数索引(哈希表预处理 Or 蓄水池抽样)
文章目录 Question Ideas 1.Answer( Java ) `⚡️ getOrDefault(Object key, V defaultValue)` Code①( HashMap 实现 ...
- Java实现 LeetCode 398 随机数索引
398. 随机数索引 给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引. 您可以假设给定的数字一定存在于数组中. 注意: 数组大小可能非常大. 使用太多额外空间的解决方案将不会通过测试 ...
- 398. 随机数索引 ( 设计 )
LeetCode:398. 随机数索引 要求返回 target 在数组中随机的一个下标 留意,这个数组不是有序的,有序的话使用 二分查找. 这里无序的, 直接保存相同元素的下标,然后随机返回 AC C ...
最新文章
- 【bzoj2751】[HAOI2012]容易题(easy) 数论,简单题
- VLAN TRUNK 链路聚合 网络层路由器
- 二叉树的遍历实现-2(三级)
- window.onbeforeunload() 事件调用ajax的解决方法
- BZOJ 2440 完全平方数(莫比乌斯-容斥原理)
- Android 面向切面编程-aspjectj应用
- php 压缩js css文件,PHP实现动态压缩js与css文件的方法
- Python之面向对象的程序设计
- apache tuscany(一)
- jQuery.qrcode 生成二维码,并使用 jszip、FileSaver 下载 zip 压缩包至本地。
- 点餐系统ip地址_教你一步一步做无线点餐项目(登录篇)
- 采访:新浪微博架构师兼首席PHP技术顾问惠新宸谈PHP的架构与发展
- 【历史上的今天】6 月 26 日:EDSAC 计算机之父诞生;B 站成立;Skype 创始人出生
- python中常用于输出信息的语句函数是print括号_第十四课我们研究一下常用的print()函数,翻看了一下Python宝典...
- linux获取网卡协议地址,读取linux下的网络设备的mac地址与发送原始数据包 (2011-11-23 20:11)...
- IT企业内部系统运营推广的六种方法
- 矩阵与矩阵的乘法运算
- Android应用启动之从Launcher拉起APP(三)
- 项目数据字典数据导入导出
- Prefix-Tuning: Optimizing Continuous Prompts for Generation翻译
热门文章
- Spring Autowire自动装配(转http://lep1985520.blog.163.com/blog/static/56600480200901441338486/)
- java 废弃方法_在Java中使用Deprecated方法或类是错误的吗?
- 困在双11“流量仓”的小红书,能否撑起200亿美元估值?
- Erlang并发编程(五) --- bigwig
- 天玑9000和骁龙888plus哪个好
- 微信吸粉技巧之:微社区
- HTTP状态代码2XX、3XX、4XX、5XX分析
- 论文阅读:ICCV2021 TransReID: Transformer-based Object Re-Identifification
- 前台jQuery实现图片轮播
- 一个游戏创业者如何跳出模式