作者: 负雪明烛
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. nodejs-Cluster模块

    JavaScript 标准参考教程(alpha) 草稿二:Node.js Cluster模块 GitHub TOP Cluster模块 来自<JavaScript 标准参考教程(alpha)&g ...

  2. linux之wc命令详解

    Linux系统中wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式 wc [options] 文件... 2.命令功能 统计指定文件中的字 ...

  3. 如何从 100 亿 URL 中找出相同的 URL?

    题目描述 给定 a.b 两个文件,各存放 50 亿个 URL,每个 URL 各占 64B,内存限制是 4G.请找出 a.b 两个文件共同的 URL. 解答思路 每个 URL 占 64B,那么 50 亿 ...

  4. redis安装与简单实用

    1.在Linux上redis的安装时十分简单的: 第一步:wget http://download.redis.io/releases/redis-2.8.12.tar.gz 解压: tar zxvf ...

  5. URL+http协议

  6. spring注解-web

    以往进行web项目开发都需要在web.xml配置servlet.filter.listener,在Servlet3.0可以通过注解的方式配置它们(注意:必须用tomcat7以上版本) @WebServ ...

  7. 【Linux】【Shell】【text】grep

    grep: Global search REgular expression and Print out the line. 作用:文本搜索工具,根据用户指定的"模式(过滤条件)" ...

  8. 避免警报疲劳:每个 K8s 工程团队的 8 个技巧

    避免警报疲劳:每个 K8s 工程团队的 8 个技巧 监控 Kubernetes 集群并不容易,警报疲劳通常是一个问题.阅读这篇文章,了解减少警报疲劳的有用提示. 如果您是随叫随到团队的一员,您可能知道 ...

  9. DMA(Data Migration Assistant)迁移SQLServer数据库

    DMA适用于 本地SQLServer向Azure SQL Database迁移 两台不同的数据库服务器之间迁移 高版本->低版本 或 低版本->高版本 本文以两台不同服务器的低版本(SQL ...

  10. Jsp/servlet分页五要素

    分页5要素: * 1)pageIndex 当前页 * 2)startIndex 从第几条数据开始 * 3)countAll 总条目数 * 4)pageSize 每页大小 * 5)pageCount 总 ...