作者: 负雪明烛
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. 11.13python第一周周末练习

    2.请输出你的基本个人信息 3.结合逻辑判断,写一个不同学生分数,输出良好,优秀,分数不及格 循环输出 字符串的替换. 以什么开头startwith 以什么结尾endwith 列表转为字符串 字符串转 ...

  2. xmake v2.6.1 发布,使用 Lua5.4 运行时,Rust 和 C++ 混合编译支持

    xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...

  3. 学习java的第十四天

    一.今日收获 1.完成了手册第二章没有验证完成的例题 2.预习了第三章的算法以及for语句与if语句的用法 二.今日难题 1.验证上出现问题,没有那么仔细. 2.第二章还有没有完全理解的问题 三.明日 ...

  4. LeetCode最富有客户的资产总量

    最富有客户的资产总量 题目描述 给你一个 m * n 的整数网格 accounts,其中 account[i][j]是第 i 位客户在第 j 家银行托管的资产数量.返回最富有客户所拥有的资产总量. 客 ...

  5. 大数据学习day32-----spark12-----1. sparkstreaming(1.1简介,1.2 sparkstreaming入门程序(统计单词个数,updateStageByKey的用法,1.3 SparkStreaming整合Kafka,1.4 SparkStreaming获取KafkaRDD的偏移量,并将偏移量写入kafka中)

    1. Spark Streaming 1.1 简介(来源:spark官网介绍) Spark Streaming是Spark Core API的扩展,其是支持可伸缩.高吞吐量.容错的实时数据流处理.Sp ...

  6. 商业爬虫学习笔记day3

    一. 付费代理发送请求的两种方式 第一种方式: (1)代理ip,形式如下: money_proxy = {"http":"username:pwd@192.168.12. ...

  7. 【Git项目管理】分布式 Git - 分布式工作流程

    分布式 Git - 分布式工作流程 你现在拥有了一个远程 Git 版本库,能为所有开发者共享代码提供服务,在一个本地工作流程下,你也已经熟悉了基本 Git 命令.你现在可以学习如何利用 Git 提供的 ...

  8. c学习 - 第八章:函数

    8.7 数组作函数的参数 1.数组元素作函数的参数--值传递,单向传递 2.数组名做函数的参数--地址传送 (1)实参:数组名做实参,传递的是数组首元素的地址 (2)形参:使用同类型的数组名或指针变量 ...

  9. ReactiveCocoa操作方法-秩序

    doNext:      执行Next之前,会先执行这个Block doCompleted:      执行sendCompleted之前,会先执行这个Block - (void)doNext { [ ...

  10. Spring(4):Mybatis和Spring整合

    第一步:创建数据库 MySQL代码 1 CREATE DATABASE `mybatis` ; 2 3 USE `mybatis`; 4 5 CREATE TABLE `user` ( 6 `id` ...