Leetcode 剑指 Offer II 071.按权重随机选择

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定一个正整数数组 w ,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。

例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。

也就是说,选取下标 i 的概率为 w[i] / sum(w) 。

示例 1:

  • 输入:
    • inputs = [“Solution”,“pickIndex”]
    • inputs = [[[1]],[]]
  • 输出:
    • [null,0]
  • 解释:
    • Solution solution = new Solution([1]);
    • solution.pickIndex(); // 返回 0,因为数组中只有一个元素,所以唯一的选择是返回下标 0。

示例 2:

  • 输入:
    • inputs = [“Solution”,“pickIndex”,“pickIndex”,“pickIndex”,“pickIndex”,“pickIndex”]
    • inputs = [[[1,3]],[],[],[],[],[]]
  • 输出:
    • [null,1,1,1,1,0]
  • 解释:
    • Solution solution = new Solution([1, 3]);
    • solution.pickIndex(); // 返回 1,返回下标 1,返回该下标概率为 3/4 。
    • solution.pickIndex(); // 返回 1
    • solution.pickIndex(); // 返回 1
    • solution.pickIndex(); // 返回 1
    • solution.pickIndex(); // 返回 0,返回下标 0,返回该下标概率为 1/4 。
    • 由于这是一个随机问题,允许多个答案,因此下列输出都可以被认为是正确的:
    • [null,1,1,1,1,0]
    • [null,1,1,1,1,1]
    • [null,1,1,1,0,0]
    • [null,1,1,1,0,1]
    • [null,1,0,1,0,0]
    • 诸若此类。

提示:

  • 1 <= w.length <= 10000
  • 1 <= w[i] <= 10^5
  • pickIndex 将被调用不超过 10000 次

题目思考

  1. 如何设计随机算法?
  2. 如何优化时间复杂度?

解决方案

思路
  • 分析题目, 要考虑每个下标的权重, 我们显然不能直接随机取[0,n)的下标, 这样会导致每个下标取到的概率相同, 如何解决呢?
  • 根据题目例子, 我们可以发现, 每个下标的取值概率等于其权重除以权重总和
  • 利用这一点, 假设权重总和是 total, 我们随机取[0,total)之间的某个数字, 然后判断它落在了哪个下标的范围内, 这样就把下标权重考虑在内了
  • 举个例子, 假设数组 w 是[3,2,4], 那么总权重和就是3+2+4=9
  • 下标 0 的权重是 3, 它负责的范围是[0,2]
  • 下标 1 的权重是 2, 它负责的范围是[3,4]
  • 下标 2 的权重是 4, 它负责的范围是[5,8]
  • 我们随机取[0,9)之间的某个数字, 它落在哪个下标范围就返回哪个下标, 这样就保证了每个下标的取值概率等于其权重除以权重总和
  • 有了思路后, 如何写出代码呢?
  • 不难发现每个下标的负责范围的起点就是其前缀和, 即[0,3,5,9], 注意最后的 9 代表了总和, 不属于某个下标起点
  • 所以我们可以在初始化时求出原始数组对应的前缀和数组 sms, 最后一个元素sms[-1]就是总和
  • 然后 pickIndex 时随机取[0,sms[-1])之间的数字 x, 并从头开始遍历前缀和数组, 找到第一个满足sms[i]<=x<sms[i+1]的下标 i, 即为考虑权重后随机选取的下标
  • 不过上述查找过程需要线性遍历, 时间复杂度是 O(N), 能否继续优化呢?
  • 注意到题目给出的是正整数数组, 所以前缀和是单调递增的, 我们可以利用二分查找来优化
  • 这里我们能够完美利用 Python 提供的右二分 bisect_right, 它的语义是:
    • 如果数字存在于查找数组, 返回对应下标加 1
    • 如果数字不存在, 则返回首个大于该数字的下标或数组长度(如果已有数字都不大于查找数字时)
  • 这样右二分查找到的下标正是所需下标的下一个下标, 同样拿上面例子举例:
    • 假如查找数字是 0, 则右二分返回下标 1, 所需下标是 0
    • 假如查找数字是 1, 则右二分返回下标 1, 所需下标是 0
    • 假如查找数字是 2, 则右二分返回下标 1, 所需下标是 0
    • 假如查找数字是 3, 则右二分返回下标 2, 所需下标是 1
    • 假如查找数字是 4, 则右二分返回下标 2, 所需下标是 1
  • 大家如果感兴趣的话也可以自己尝试实现这个二分查找的过程, 基本类似前面的题目Leetcode 剑指 Offer II 068.搜索插入位置, 只需要稍作改动, target 存在时返回对应下标加 1, 而不是下标本身
  • 下面代码中有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(logN): 每次 pickIndex 使用二分查找, 时间复杂度是 O(logN)
  • 空间复杂度 O(N): 需要额外存储前缀和数组
代码
class Solution:
    def __init__(self, w: List[int]):
        # 前缀和+二分查找
        self.sms = [0]
        for x in w:
            # 统计前缀和数组
            self.sms.append(x + self.sms[-1])

    def pickIndex(self) -> int:
        # 随机选择[0,数字总和)之间的一个数字x
        x = random.randrange(0, self.sms[-1])
        # 二分查找当前数字落在了哪个下标的范围内
        # 这里使用右二分bisect_right, 且二分得到的下标要减1
        return bisect.bisect_right(self.sms, x) - 1

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/501530.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浅谈Spring体系的理解

浅谈Spring知识体系 Spring Framework架构图Spring家族技术生态全景图XMind汇总 本文不涉及细节&#xff0c;主要回答两个问题&#xff1a; Spring家族技术生态全景图有哪些Spring Framework架构下每个模块有哪些东西&#xff0c;以及部分模块之间的关联关系 Spring Framework架…

NC269391 炸鸡块哥哥的粉丝题

题目描述 智乃作为炸鸡块哥哥的粉丝&#xff0c;做了一场炸鸡块哥哥的比赛后得出一个结论&#xff0c;那就是炸鸡块哥哥的话&#xff0c;最多只能信半句。 现在给你一个长度为N的字符串S&#xff0c;请输出前 个字符&#xff0c;表示只能相信半句话。 例如当炸鸡块哥哥说&…

使用uni-app开发微信小程序并实现页面间的跳转

一、下载需要的开发工具 HBuilderX 微信开发者工具 HBuilderX HBuilderX-高效极客技巧 (dcloud.io) 微信开发者工具 下载 / 开发版更新日志 (qq.com) 二、新建项目 通过vue-cli命令行创建项目 参考&#xff1a; uni-app官网 (dcloud.net.cn) 2.1全局安装 vue-cli npm i…

新网站秒收录技术,新网站百度收录时间

在建立新网站后&#xff0c;让它尽快被搜索引擎收录是网站主最为关注的事情之一。百度作为中国最大的搜索引擎&#xff0c;网站被其快速收录对于增加曝光和流量至关重要。本文将介绍一些新网站秒收录技术&#xff0c;以及一般情况下新网站被百度收录需要的时间。 新网站秒收录技…

如何将图片变小到200k?一键图片压缩指定大小

不管是在网站上传资料&#xff0c;还是在社交软件中发送图片&#xff0c;对于图片的体积都是有限制的&#xff0c;比如超出200k就无法操作&#xff0c;这时候简单的做法就是压缩图片大小&#xff0c;下面就给大家总结了几个不错的图片压缩技巧&#xff0c;其中有些方法可以直接…

【OJ】动归练习五之子组串

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 1. 53. 最大子数组和1.1 分析1.2 代码 2. 918. 环形子数组的最大和2.1 分析2.2 代码 3. 152. 乘积最大子数组3.1 分析3.2 代码 4. 1567. 乘积为正数的最长子数组长度4.1 分析4.2 代码 1. 53. 最大子数组和 1.1 分析 一、…

解锁网络新境界:国内IP地址好用的有哪些?

在互联网的世界里&#xff0c;IP地址是每一个网络设备的“身份证”&#xff0c;是实现网络通信的关键。在国内&#xff0c;随着网络技术的不断发展和普及&#xff0c;IP地址的使用和管理也日益受到关注。虎观代理将深入解析国内IP地址的选择与使用&#xff0c;为大家推荐一些好…

爬取b站音频和视频数据,未合成一个视频

一、首先找到含有音频和视频的url地址 打开一个视频&#xff0c;刷新后&#xff0c;找到这个包&#xff0c;里面有我们所需要的数据 访问这个数据包后&#xff0c;获取字符串数据&#xff0c;用正则提取&#xff0c;再转为json字符串方便提取。 二、获得标题和音频数据后&…

XXII Open Cup, Grand Prix of Daejeon C. AND PLUS OR(思维 结论)

题目 给定n(n<20)&#xff0c;再输入2^n个数&#xff0c;分别代表a[0]到a[2^n-1]&#xff0c;第i个数ai(0<ai<1e7) 问是否存在一对下标i、j满足a[i]a[j]<a[i&j]a[i|j] 如果不存在&#xff0c;输出-1&#xff0c;否则输出任意一对(i,j)即可 思路来源 官方题…

Https【Linux网络编程】

目录 一、为什么需要https 二、常见加密方法 1、对称加密 2、非对称加密 3、数据指纹 三、选择什么加密方案&#xff1f; 方案一&#xff1a;对称加密&#xff08;&#xff09; 方案二&#xff1a;双方使用非对称加密&#xff08;效率低&#xff09; 方案三&#xff1a…

电子级高纯PFA材质实验室器皿耗材PFA漏斗PFA试剂瓶PFA烧杯

PFA三角漏斗&#xff0c;整体均是PFA材质&#xff0c;无污染风险&#xff0c;可高压灭菌。 尺寸&#xff1a;外径40mm、160mm PFA三角漏斗 特点&#xff1a; 1、一体式成型&#xff0c;结构稳定&#xff1b; 2、化学耐受性强&#xff0c;耐受强酸、强碱以及各种有机溶剂&…

C语言例3-1:阅读下列程序,写出程序运行的结果。

代码如下&#xff1a; #include <stdio.h> int main(void) {int x8;do{printf("*");x--;x--;}while(x0);printf("\n");return 0; } 结果如下&#xff1a; 分析&#xff1a; do-while语句&#xff0c;先执行后判断先打印 "*" &#xff0…

58集团校园招聘(含内推码)

招聘链接&#xff1a;校招链接 内推码在后文。 内推码 填写我的推荐码&#xff1a;EVBAJS 投递

1、Cocos Creator 基础入门

目录 Cocos Creator 是什么&#xff1f; 语言支持 功能特性 工作流程 功能模块 相关游戏 参考 Cocos Creator 是什么&#xff1f; Cocos Creator 既是一款高效、轻量、免费开源的跨平台 2D&3D 图形引擎&#xff0c;也是一个实时 2D&3D 数字内容创作平台。拥有…

线上剧本杀小程序成为行业发展大势,商家该如何选择?

在过去的几年中&#xff0c;剧本杀成为了年轻人娱乐社交的新方式&#xff0c;深受年轻人的喜欢&#xff0c;市场规模持续上升。 目前&#xff0c;剧本杀的布局也向线上发展&#xff0c;线上剧本杀的发展势头持续上升&#xff0c;规模也在持续扩大中。通过开发剧本杀小程序&…

在Windows的Docker上部署Mysql服务

在我们做一些和数据库相关的测试时&#xff0c;往往需要快速部署一个数据库作为数据源。如果开发环境是Windows&#xff0c;且开发的代码不依赖于系统&#xff0c;即不用在linux上做开发&#xff0c;则可以将全套环境都部署在Windows上。 本地安装数据库会污染操作系统环境&…

某某45浏览器干净卸载详细教程

​ 某某45是个什么软件&#xff1f;某某45浏览器是病毒吗&#xff1f;这个问题想必困惑着很多小伙伴&#xff0c;新装机的电脑总是有某某45全家桶。那么今天咱们一起看看。 ​ 某某45是个什么软件 某某45是一个中国软件公司&#xff0c;提供各种软件产品和服务。其中&#xff0…

【c 语言 】malloc函数详解

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

FFMPEG C++封装(一)(C++ FFMPEG)

1 概述 FFMPEG是一个C语言开源视音频编解码库。本文将FFMPG4.1.3进行C封装&#xff0c;形成C FFMPG库。 2 架构 架构图如下所示&#xff1a; 架构说明: Init 初始化FFMPEG库。IStream 输入流&#xff0c;FFMPEG的输入音视频文件。Packet 音视频数据包Decoder 音视频编码器F…

字符集 --java学习笔记

字符集 为了将字符存进计算机&#xff0c;所以有了字符集 标准ASCI字符集 ASCl(American standard Code for Information Interchange):美国信息交换标准代码&#xff0c;包括了英文、符号等标准ASCI使用1个字节存储一个字符&#xff0c;首尾是0&#xff0c;总共可表示128个…