作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/random-pick-index/description/

题目描述

Given an array of integers with possible duplicates, randomly output the index of a given target number. You can assume that the given target number must exist in the array.

Note:
The array size can be very large. Solution that uses too much extra space will not pass the judge.

Example:

int[] nums = new int[] {1,2,3,3,3};
Solution solution = new Solution(nums);

// pick(3) should return either index 2, 3, or 4 randomly. Each index should have equal probability of returning.
solution.pick(3);

// pick(1) should return 0. Since in the array only nums[0] is equal to 1.
solution.pick(1);

题目大意

在一个数组中寻找一个数字的索引位置。如果有多个,等概率的随机返回其中的任何一个。

解题方法

每次遍历索引

使用了一个比较讨巧的方法,用O(n)的时间复杂度,对整个数组进行遍历,这样如果有数字和target相等就保存下其索引位置。再从这些索引位置中等概率返回任意一个即可。

python代码如下:

class Solution(object):

    def __init__(self, nums):
""" :type nums: List[int]
:type numsSize: int
"""
self.nums = nums def pick(self, target):
"""
:type target: int
:rtype: int
"""
idxs = []
for i, num in enumerate(self.nums):
if num == target:
idxs.append(i)
return idxs[random.randint(0, len(idxs) - 1)] # Your Solution object will be instantiated and called as such:
# obj = Solution(nums)
# param_1 = obj.pick(target)

字典保存索引

上面的做法每次pick的时候都要遍历一次,时间复杂度太高。一个利用空间换时间的方法就是提前使用字典把每个数字在哪些数字出现都保存好,然后随机一个返回就行。每次Pick的时间复杂度是O(1)。

C++代码如下:

class Solution {
public:
Solution(vector<int> nums) {
for (int i = 0; i < nums.size(); ++i) {
m_[nums[i]].push_back(i);
}
} int pick(int target) {
auto v = m_[target];
int s = v.size();
int i = rand() % s;
return v[i];
}
private:
unordered_map<int, vector<int>> m_;
}; /**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(nums);
* int param_1 = obj.pick(target);
*/

蓄水池抽样

看到这个题,想到382. Linked List Random Node,知道它考察的是蓄水池抽样算法。384. Shuffle an Array也有用到。

蓄水池采样算法(Reservoir Sampling)是说在一个流中,随机选择k个数字,保证每个数字被选择的概率相等。

算法的过程:

假设数据序列的规模为 n,需要采样的数量的为 k。

首先构建一个可容纳 k 个元素的数组,将序列的前 k 个元素放入数组中。

然后从第 k+1 个元素开始,以 k/cnt 的概率来决定该元素是否被替换到数组中(数组中的元素被替换的概率是相同的)。 当遍历完所有元素之后,数组中剩下的元素即为所需采取的样本。

这个题中k = 1。

C++代码如下:

class Solution {
public:
Solution(vector<int> nums) : nums_(nums) {
} int pick(int target) {
int cnt = 0;
int res = -1;
for (int i = 0; i < nums_.size(); ++i) {
int n = nums_[i];
if (n != target) continue;
++cnt;
if (rand() % cnt == 0)
res = i;
}
return res;
}
private:
vector<int> nums_;
}; /**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(nums);
* int param_1 = obj.pick(target);
*/

参考资料:

http://www.cnblogs.com/grandyang/p/5875509.html
https://www.cnblogs.com/snowInPluto/p/5996269.html

日期

2018 年 3 月 13 日
2019 年 2 月 26 日 —— 二月就要完了

【LeetCode】398. Random Pick Index 解题报告(Python & C++)的更多相关文章

  1. [LeetCode] 398. Random Pick Index ☆☆☆

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

  2. [leetcode] 398. Random Pick Index

    我是链接 看到这道题,想到做的几道什么洗牌的题,感觉自己不是很熟,但也就是rand()函数的调用,刚开始用map<int, vector<int >>来做,tle,后来就想着直 ...

  3. 398. Random Pick Index - LeetCode

    Question 398. Random Pick Index Solution 思路:重点是如果数据中有多个数target相等,要从这些数中随机取一个,根据例题 假设输入是: int[] nums ...

  4. 398. Random Pick Index

    随机返还target值的坐标(如果存在多个target). 不太明白为什么这个题是M难度的. 无非是要么弄TABLE之类的,开始麻烦点,但是pick的时候直接PICK出来就行了. 要么开始简单点,都存 ...

  5. 398. Random Pick Index随机pick函数

    [抄题]: Given an array of integers with possible duplicates, randomly output the index of a given targ ...

  6. [LC] 398. Random Pick Index

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

  7. 398 Random Pick Index 随机数索引

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

  8. 【LeetCode】62. Unique Paths 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/unique-pa ...

  9. 【LeetCode】880. Decoded String at Index 解题报告(Python)

    [LeetCode]880. Decoded String at Index 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...

随机推荐

  1. Shell中 ##%% 操作变量名

    在linxu平台下少不了对变量名的处理,今天记录下shell中 ##%% 对变量名的操作. #操作左侧,%操作右侧. #号处理方式: 对于单个#,处理对象为变量中指定的第一个符号左侧字符串, 对于两个 ...

  2. matplotlib 画饼图

    有个瑕疵,某一块儿比例过小时,文字会重叠. 1 def pizza(data,labs,title): 2 import matplotlib 3 import matplotlib.pyplot a ...

  3. Linux—&#160;查看系统的位数

    [root@zf-test-web01-4 ~]# file /bin/ls           #"/bin/ls" is a binary file /bin/ls: ELF ...

  4. 关于latex简历几个非常有用的命令

        大家知道latex是最好的排版系统,用来写论文,排版非常漂亮,用来做简历可以提升逼格,下面介绍几个有用的命令 几个有用的命令 section.cventry.cvitem.cvlistit ...

  5. Vue3 中有哪些值得深究的知识点?

    众所周知,前端技术一直更新很快,这不 vue3 也问世这么久了,今天就来给大家分享下vue3中值得注意的知识点.喜欢的话建议收藏,点个关注! 1.createApp vue2 和 vue3 在创建实例 ...

  6. 学习java的第二十六天

    一.今日收获 1.java完全学习手册第三章算法的3.2排序,比较了跟c语言排序上的不同 2.观看哔哩哔哩上的教学视频 二.今日问题 1.快速排序法的运行调试多次 2.哔哩哔哩教学视频的一些术语不太理 ...

  7. Android系统编程入门系列之硬件交互——多媒体麦克风

    在多媒体摄像头及相关硬件文章中,对摄像头的使用方式需要区分应用程序的目标版本以使用不同的代码流程,而与之相比,麦克风硬件的使用就简单多了. 麦克风及相关硬件 麦克风硬件在移动设备上作为音频的采集设备, ...

  8. 100个Shell脚本——【脚本2】截取字符串

    [脚本2]截取字符串 一.脚本 现有一个字符串如下: http://www.aaa.com/root/123.htm 请根据以下要求截取出字符串中的字符: 1.取出www.aaa.com/root/1 ...

  9. 【Netty】最透彻的Netty原理架构解析

    这可能是目前最透彻的Netty原理架构解析 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希望给大家在实际开发实践.学习开源项目方面提供参考. ...

  10. 通过js禁用浏览器的回退事件

    js代码: <script> history.pushState(null, null, document.URL); window.addEventListener('popstate' ...