作者: 负雪明烛
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. Oracle-distinct()用法、count(distinct( 字段A || 字段B))是什么意思?distinct多个字段

    0.distinct用法 在oracle中distinct的使用主要是在查询中去除重复出现的数据 直接在字段前加distinct关键字即可,如:select distinct 名字 from tabl ...

  2. tomcat在eclipse上发布,Perference下的server找不到解决办法

    help--->Install New software得到如下所示 下面work with选项的内容与你的eclipse版本有关 我的eclipse版本为eclipse-java-2019-0 ...

  3. Angular @Input讲解及用法

    1.什么是@input @input的作用是定义模块输入,是用来让父级组件向子组件传递内容. 2.@input用法 首先在子组件中将需要传递给父组件的变量用@input()修饰 需要在子组件ts文件i ...

  4. 编程之美Q1

    题目 和数书页有点类似,就直接数吧 #include<iostream> using namespace std; class q1 { public: size_t func(size_ ...

  5. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍

    其他链接 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 ...

  6. centos7安装Docker详细步骤(无坑版教程)

    一.安装前必读 在安装 Docker 之前,先说一下配置,我这里是Centos7 Linux 内核:官方建议 3.10 以上,3.8以上貌似也可. 注意:本文的命令使用的是 root 用户登录执行,不 ...

  7. Output of C++ Program | Set 13

    Predict the output of following C++ program. 1 #include<iostream> 2 using namespace std; 3 4 c ...

  8. Linux磁盘与文件系统原理

    这一章主要是原理性的,介绍了Linux文件系统的运作原理.涉及到很多计算机组成和操作系统的原理性知识,这部分知识很多都忘了,在这里复习下.    我们只看本章第1,2节.--------------- ...

  9. 【编程思想】【设计模式】【行为模式Behavioral】Specification

    Python版 https://github.com/faif/python-patterns/blob/master/behavioral/specification.py #!/usr/bin/e ...

  10. 【Linux】【Services】【SaaS】Docker+kubernetes(13. 部署Jenkins/Maven实现代码自动化发布)

    1. 简介 Jenkins: 官方网站:https://jenkins.io/ 下载地址:https://jenkins.io/download/ war包下载:http://mirrors.jenk ...