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,数字总和)之间的一个数字xx = random.randrange(0, self.sms[-1])# 二分查找当前数字落在了哪个下标的范围内# 这里使用右二分bisect_right, 且二分得到的下标要减1return bisect.bisect_right(self.sms, x) - 1

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

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《AIGC重塑金融:AI大模型驱动的金融变革与实践》

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-oBSlqt4Vga1he7DL {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

聊聊k8s服务发现的优缺点

序 本文主要研究一下使用k8s服务发现的优缺点 spring cloud vs kubernetes 这里有张spring cloud与kubernetes的对比&#xff0c;如果将微服务部署到kubernetes上面&#xff0c;二者有不少功能是重复的&#xff0c;可否精简。 这里主要是讲述一下如果不使用独立的服务发现&am…

websocket 局域网 webrtc 一对一 视频通话的实例

基本介绍 使用websocket来 WebRTC 建立连接时的 数据的传递和交换。 WebRTC 建立连接时&#xff0c;通常需要按照以下顺序执行一些步骤&#xff1a; 1.创建本地 PeerConnection 对象&#xff1a;使用 RTCPeerConnection 构造函数创建本地的 PeerConnection 对象&#xff0c;该…

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

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

FreeRTOS day1

1.总结keil5下载代码和编译代码需要注意的事项 需要与板子连通 配置完成后才点击下载 2.总结STM32Cubemx的使用方法和需要注意的事项 下载支持包 打开芯片配置界面 3.总结STM32Cubemx配置GPIO的方法

【动手学深度学习-pytorch】9.2长短期记忆网络(LSTM)

长期以来&#xff0c;隐变量模型存在着长期信息保存和短期输入缺失的问题。 解决这一问题的最早方法之一是长短期存储器&#xff08;long short-term memory&#xff0c;LSTM&#xff09; (Hochreiter and Schmidhuber, 1997)。 它有许多与门控循环单元&#xff08; 9.1节&…

目标检测评价标准

主要借鉴&#xff1a;https://github.com/rafaelpadilla/Object-Detection-Metrics?tabreadme-ov-file 主要评价指标、术语&#xff1a; Intersection Over Union (IOU)&#xff1a;两个检测框交集面积与并集面积的比值 True Positive (TP)&#xff1a;IOU大于阈值的检测框…

uniapp实现列表动态添加

1.效果图&#xff1a; 2.代码实现&#xff1a; 这里没有用uniapp提供的uni-list控件 <template> <view id"app"> <!-- 这里为了让标题&#xff08;h&#xff09;居中展示&#xff0c;给h标签设置了父标签&#xff0c;并设置父标签text-…

物联网实战--入门篇之(四)嵌入式-UART驱动

目录 一、串口简介 二、串口驱动设计 三、串口发送 四、串口接收处理 五、PM2.5数据接收处理 六、printf重定义 七、总结 一、串口简介 串口在单片机的开发中属于非常常用的外设&#xff0c;最基本的都会预留一个调试串口用来输出调试信息&#xff0c;串口时序这里就不谈…

既有理论深度又有技术细节——深度学习计算机视觉

推荐序 我曾经试图找到一本既有理论深度、知识广度&#xff0c;又有技术细节、数学原理的关于深度学习的书籍&#xff0c;供自己学习&#xff0c;也推荐给我的学生学习。虽浏览文献无数&#xff0c;但一直没有心仪的目标。两周前&#xff0c;刘升容女士将她的译作《深度学习计…

java中的单例模式

一、描述 单例模式就是程序中一个类只能有一个对象实例 举个例子: //引出单例模式&#xff0c;一个类中只能由一个对象实例 public class Singleton1 {private static Singleton1 instance new Singleton1();//通过这个方法来获取实例public static Singleton1 getInstance…

Verilog语法回顾--门级和开关级模型

目录 门和开关的声明 门和开关类型 支持驱动强度的门 延迟 实例数组 and&#xff0c;nand&#xff0c;nor&#xff0c;or&#xff0c;xor&#xff0c;xnor buf&#xff0c;not bufif1&#xff0c;bufif0&#xff0c;notif1&#xff0c;notif0 MOS switches Bidirecti…

TSINGSEE青犀智慧工厂视频汇聚与安全风险智能识别和预警方案

在智慧工厂的建设中&#xff0c;智能视频监控方案扮演着至关重要的角色。它不仅能够实现全方位、无死角的监控&#xff0c;还能够通过人工智能技术&#xff0c;实现智能识别、预警和分析&#xff0c;为工厂的安全生产和高效运营提供有力保障。 TSINGSEE青犀智慧工厂智能视频监…

公司官网怎么才会被百度收录

在互联网时代&#xff0c;公司官网是企业展示自身形象、产品与服务的重要窗口。然而&#xff0c;即使拥有精美的官网&#xff0c;如果不被搜索引擎收录&#xff0c;就无法被用户发现。本文将介绍公司官网如何被百度收录的一些方法和步骤。 1. 创建和提交网站地图 创建网站地图…

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

代码如下&#xff1a; #include <stdio.h> int main(void) {int i1,s3;do{si;if(s%70) continue;else i;}while(s<15);printf("%d",i);return 0; } 结果如下&#xff1a; 分析&#xff1a; s314437741111617i3468

四、e2studio VS STM32CubeIDE之STM32CubeIDE线程安全解决方案

目录 一、概述/目的 二、原因和办法 三、线程安全问题的描述 四、STM32解决方案 4.1 通用策略 4.2 RTOS策略 4.3 策略的讲解 4.3.1 裸机应用(策略2、3) 4.3.2 RTOS应用(策略4、5) 五、关键源码 四、e2studio VS STM32CubeIDE之STM32CubeIDE线程安全解决方案 一、概述…

Spring Boot简介及案例

文章目录 Spring Boot简介以下是一个简单的 Spring Boot Web 应用实例**步骤 1&#xff1a;创建 Spring Boot 项目****步骤 2&#xff1a;编写 RESTful 控制器****步骤 3&#xff1a;配置主类****步骤 4&#xff1a;运行并测试应用** Spring Boot简介 Spring Boot 是一个用于简…

怎么让ChatGPT批量写作原创文章

随着人工智能技术的不断发展&#xff0c;自然语言处理模型在文本生成领域的应用也日益广泛。ChatGPT作为其中的佼佼者之一&#xff0c;凭借其强大的文本生成能力和智能对话特性&#xff0c;为用户提供了一种高效、便捷的批量产出内容的解决方案。以下将就ChatGPT批量写作内容进…

【AI】命令行调用大模型

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 【AI】命令行调用大模型引入正文初始化项目撰写脚本全局安装 成果展示 【AI】命令…

Ubuntu20.04LTS+uhd3.15+gnuradio3.8.1源码编译及安装

文章目录 前言一、卸载本地 gnuradio二、安装 UHD 驱动三、编译及安装 gnuradio四、验证 前言 本地 Ubuntu 环境的 gnuradio 是按照官方指导使用 ppa 的方式安装 uhd 和 gnuradio 的&#xff0c;也是最方便的方法&#xff0c;但是存在着一个问题&#xff0c;就是我无法修改底层…