【LeetCode】动态规划—删除并获得点数(附完整Python/C++代码)
动态规划—#740. 删除并获得点数
- 前言
- 题目描述
- 基本思路
- 1. 问题定义:
- 2. 理解问题和递推关系:
- 3. 解决方法:
- 4. 进一步优化:
- 5. 小总结:
- 代码实现
- Python3代码实现
- Python 代码解释
- C++代码实现
- C++ 代码解释
- 总结:
前言
给你一个整数数组 n u m s nums nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 n u m s [ i ] nums[i] nums[i] ,删除它并获得 n u m s [ i ] nums[i] nums[i] 的点数。之后,你必须删除 所有 等于 n u m s [ i ] − 1 nums[i] - 1 nums[i]−1 和$ nums[i] + 1$ 的元素。
开始你拥有 0 0 0 个点数。返回你能通过这些操作获得的最大点数。
题目描述
基本思路
1. 问题定义:
在这个问题中,我们有一个数组 n u m s [ ] nums[] nums[],每个元素代表一个数字。你可以选择删除某个数字 x x x ,并获得 x x x 点数。然而,每当你删除一个数字 x x x ,与 x x x 相邻的数字 x − 1 x-1 x−1 和 x + 1 x+1 x+1 也会从数组中删除。问题要求的是:你通过删除数字获得的最大点数是多少?
2. 理解问题和递推关系:
这个问题类似于"打家劫舍"问题,可以转化为一个动态规划问题。每次删除某个数字时,你既获得了它的值,也会让相邻的数字无法再被选择。因此,可以把问题转化为:每个数 x x x 要么选择,要么跳过。
我们将问题理解为两个选择:
- 选择删除某个数字 x x x :那么你会获得 x x x 出现的总值 x x x *出现次数,同时不能再选择 x − 1 x-1 x−1 和 x + 1 x+1 x+1 。
- 不选择删除某个数字 x x x :那么你可以选择去考虑删除其他数字。
为了将问题转化成打家劫舍的形式:
- 我们可以对 n u m s [ ] nums[] nums[] 进行预处理,统计每个数 x x x 的出现次数,然后构建一个数组 e a r n [ ] earn[] earn[],其中 e a r n [ x ] = x ∗ earn [x]=x * earn[x]=x∗ 出现次数。
- 现在,问题转化为:给定一个数组 e a r n [ ] earn[] earn[],从中选择不相邻的数,使得获得的总和最大。这就是"打家劫舍"问题的典型形式。
3. 解决方法:
- 预处理:首先统计 n u m s [ ] nums[] nums[] 中每个数字的出现次数,并构建 e a r n [ ] earn[] earn[],即 e a r n [ x ] = x ∗ earn[ x ]=\mathrm{x} * earn[x]=x∗ 出现次数。
- 递推公式:我们使用动态规划来解决该问题,设 d p [ i ] d p[i] dp[i] 表示前 i i i 个数字的最大点数。那么:
d p [ i ] = max ( d p [ i − 1 ] , d p [ i − 2 ] + earn [ i ] ) d p[i]=\max (d p[i-1], d p[i-2]+\operatorname{earn}[i]) dp[i]=max(dp[i−1],dp[i−2]+earn[i])
解释:
- d p [ i − 1 ] dp[i-1] dp[i−1] 表示我们不删除数字 i i i,因此直接继承前面的最大值。
- d p [ i − 2 ] + e a r n [ i ] dp[i-2] + earn[i] dp[i−2]+earn[i] 表示我们删除了数字 i i i,因此需要加上 e a r n [ i ] earn[i] earn[i],同时要跳过 i − 1 i-1 i−1。
- 边界条件:
- 如果数组为空,直接返回 0 0 0 。
- 如果数组只有一个元素,那么返回该元素对应的 e a r n earn earn 值。
4. 进一步优化:
在上述方法中,我们使用了一个数组 d p [ ] d p[] dp[] 来保存每个位置的最大点数。但实际上, d p [ i ] d p[i] dp[i] 只依赖于 d p [ i − 1 ] d p[i-1] dp[i−1] 和 dp[i-2],因此可以通过使用两个变量来优化空间复杂度,从 O ( n ) O(n) O(n) 降低到 O ( 1 ) O(1) O(1) 。
- 时间复杂度: O ( n ) O(n) O(n) ,因为我们需要遍历数组构建 e a r n [ ] earn[] earn[],以及进行动态规划。
- 空间复杂度:通过优化后可以降低到 O ( 1 ) O(1) O(1) ,只需要常量空间保存前两个状态。
5. 小总结:
- 问题核心:通过删除某个数获得它的总值,并且不能删除与它相邻的数。这个问题转化为典型的动态规划问题。
- 动态规划:通过计算每个数出现的总值 e a r n [ x ] earn[x] earn[x],将问题简化为选择不相邻的数求最大和的问题。
- 优化:使用两个变量保存前两个状态,减少空间消耗。
以上就是删除并获得点数问题的基本思路。
代码实现
Python3代码实现
class Solution:def deleteAndEarn(self, nums: list[int]) -> int:if not nums:return 0# 统计每个数字的总收益max_num = max(nums)earn = [0] * (max_num + 1)for num in nums:earn[num] += num# 使用动态规划来解决打家劫舍问题prev2, prev1 = 0, 0for i in range(len(earn)):current = max(prev1, prev2 + earn[i])prev2 = prev1prev1 = currentreturn prev1
Python 代码解释
- 边界条件:如果 n u m s [ ] nums[] nums[] 为空,直接返回 0 0 0。
- 统计:我们遍历 n u m s [ ] nums[] nums[],构建 e a r n [ ] earn[] earn[],其中 e a r n [ x ] = x ∗ earn[x] = x * earn[x]=x∗ 出现次数。
- 动态规划:通过 p r e v 2 prev2 prev2 和 p r e v 1 prev1 prev1 来存储前两个状态的最大值,然后根据递推公式依次更新,最终返回 p r e v 1 prev1 prev1 即为最大值。
C++代码实现
class Solution:def deleteAndEarn(self, nums: list[int]) -> int:if not nums:return 0# 统计每个数字的总收益max_num = max(nums)earn = [0] * (max_num + 1)for num in nums:earn[num] += num# 使用动态规划来解决打家劫舍问题prev2, prev1 = 0, 0for i in range(len(earn)):current = max(prev1, prev2 + earn[i])prev2 = prev1prev1 = currentreturn prev1
C++ 代码解释
- 边界条件:如果 n u m s [ ] nums[] nums[] 为空,直接返回 0 0 0。
- 统计:构建 e a r n [ ] earn[] earn[] 数组,存储每个数字的总收益。
- 动态规划:使用两个变量 p r e v 2 prev2 prev2 和 p r e v 1 prev1 prev1 来分别存储前两个状态的最大收益,遍历数组 e a r n [ ] earn[] earn[],最终返回 p r e v 1 prev1 prev1。
总结:
- 动态规划是解决此类问题的核心,将删除数字及其邻居的问题转化为典型的选择不相邻数的问题。
- 优化空间:通过使用常量空间,减少了数组存储的开销,使得算法在时间和空间上都更高效。
相关文章:

【LeetCode】动态规划—删除并获得点数(附完整Python/C++代码)
动态规划—#740. 删除并获得点数 前言题目描述基本思路1. 问题定义:2. 理解问题和递推关系:3. 解决方法:4. 进一步优化:5. 小总结: 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 给你一个整数数组 n u m s nums nums ,你可以对它进行一…...

利用 PostgreSQL 构建 RAG 系统实现智能问答
在现代信息检索和自然语言处理的场景中,检索增强生成 (Retrieval-Augmented Generation, RAG) 系统因其结合了知识库检索和生成模型的优势,成为了一种非常流行的智能问答方法。在这篇博文中,我将展示如何利用PostgreSQL作为向量存储数据库&am…...

Go 并发模式:扩展与聚合的高效并行
当你搭建好一个管道系统后,数据在各个阶段之间顺畅地流动,并根据你设定的操作逐步转换。这一切看起来像是一条美丽的溪流,然而,为什么有时候这个过程会如此缓慢呢? 在处理数据时,某些阶段可能会非常耗时,导致上游的阶段被阻塞,无法继续处理数据。这不仅影响了管道的整…...

【Transformers基础入门篇2】基础组件之Pipeline
文章目录 一、什么是Pipeline二、查看PipeLine支持的任务类型三、Pipeline的创建和使用3.1 根据任务类型,直接创建Pipeline,默认是英文模型3.2 指定任务类型,再指定模型,创建基于指定模型的Pipeline3.3 预先加载模型,再…...

java反射学习总结
最近在项目上有一个内部的CR,运用到了反射。想起之前面试的时候被面试官追问有没有在项目中用过反射,以及反射的原理和对反射的了解。 于是借此机会,学习回顾一下反射,以及在项目中可能会用到的场景。 Java 中的反射概述 反射&…...

探索C语言与Linux编程:获取当前用户ID与进程ID
探索C语言与Linux编程:获取当前用户ID与进程ID 一、Linux系统概述与用户、进程概念二、C语言与系统调用三、获取当前用户ID四、获取当前进程ID五、综合应用:同时获取用户ID和进程ID六、深入理解与扩展七、结语在操作系统与编程语言的交汇点,Linux作为开源操作系统的典范,为…...

1.4 边界值分析法
欢迎大家订阅【软件测试】 专栏,开启你的软件测试学习之旅! 文章目录 前言1 定义2 选取3 具体步骤4 案例分析 本篇文章参考黑马程序员 前言 边界值分析法是一种广泛应用于软件测试中的技术,旨在识别输入值范围内的潜在缺陷。本文将详细探讨…...

Spring IOC容器Bean对象管理-注解方式
目录 1、Bean对象常用注解介绍 2、注解示例说明 1、Bean对象常用注解介绍 Component 通用类组件注解,该类被注解,IOC容器启动时实例化此类对象Controller 注解控制器类Service 注解业务逻辑类Respository 注解和数据库操作的类,如DAO类Reso…...

OpenAI API: How to catch all 5xx errors in Python?
题意:OpenAI API:如何在 Python 中捕获所有 5xx 错误? 问题背景: I want to catch all 5xx errors (e.g., 500) that OpenAI API sends so that I can retry before giving up and reporting an exception. 我想捕获 OpenAI API…...

C++初阶学习——探索STL奥秘——标准库中的priority_queue与模拟实现
1.priority_queque的介绍 1.priority_queue中文叫优先级队列。优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。 2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元…...

PyTorch经典模型
PyTorch 经典模型教程 1. PyTorch 库架构概述 PyTorch 是一个广泛使用的深度学习框架,具有高度的灵活性和动态计算图的特性。它支持自动求导功能,并且拥有强大的 GPU 加速能力,适用于各种神经网络模型的训练与部署。 PyTorch 的核心架构包…...

C++ STL容器(三) —— 迭代器底层剖析
本篇聚焦于STL中的迭代器,同样基于MSVC源码。 文章目录 迭代器模式应用场景实现方式优缺点 UML类图代码解析list 迭代器const 迭代器非 const 迭代器 vector 迭代器const 迭代器非const迭代器 反向迭代器 迭代器失效参考资料 迭代器模式 首先迭代器模式是设计模式中…...

力扣416周赛
举报垃圾信息 题目 3295. 举报垃圾信息 - 力扣(LeetCode) 思路 直接模拟就好了,这题居然是中等难度 代码 public boolean reportSpam(String[] message, String[] bannedWords) {Map<String,Integer> map new HashMap<>()…...

vue 页面常用图表框架
在 Vue.js 页面中,常见的用于制作图表的框架或库有以下几种: ECharts: 官方网站: EChartsECharts 是一个功能强大、可扩展的图表库,支持多种图表类型,如柱状图、折线图、饼图等。Vue 集成: 可以使用 vue-echarts 插件,…...

spring 注解 - @PostConstruct - 用于初始化工作
PostConstruct 是 Java EE 5 中引入的一个注解,用于标注在方法上,表示该方法应该在依赖注入完成之后执行。这个注解是 javax.annotation 包的一部分,通常用于初始化工作,比如初始化成员变量或者启动一些后台任务。 在 Spring 框架…...

多机器学习模型学习
特征处理 import os import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.model_selection import StratifiedShuffleSplit from sklearn.impute import SimpleImputer from sklearn.pipeline import FeatureUnion fr…...

【网页设计】前言
本专栏主要记录 “网页设计” 这一课程的相关笔记。 参考资料: 黑马程序员:黑马程序员pink老师前端入门教程,零基础必看的h5(html5)css3移动端前端视频教程_哔哩哔哩_bilibili 教材:《Adobe创意大学 Dreamweaver CS6标准教材》《…...

STM32巡回研讨会总结(2024)
前言 本次ST公司可以说是推出了7大方面,几乎可以说是覆盖到了目前生活中的方方面面,下面总结下我的感受。无线类 支持多种调制模式(LoRa、(G)FSK、(G)MSK 和 BPSK)满足工业和消费物联网 (IoT) 中各种低功耗广域网 (LPWAN) 无线应…...

54 螺旋矩阵
解题思路: \qquad 这道题可以直接用模拟解决,顺时针螺旋可以分解为依次沿“右-下-左-上”四个方向的移动,每次碰到“边界”时改变方向,边界是不可到达或已经到达过的地方,会随着指针移动不断收缩。 vector<int>…...

基于STM32与OpenCV的物料搬运机械臂设计流程
一、项目概述 本文提出了一种新型的物流搬运机器人,旨在提高物流行业的物料搬运效率和准确性。该机器人结合了 PID 闭环控制算法与视觉识别技术,能够在复杂的环境中实现自主巡线与物料识别。 项目目标与用途 目标:设计一款能够自动搬运物流…...

[万字长文]stable diffusion代码阅读笔记
stable diffusion代码阅读笔记 获得更好的阅读体验可以转到我的博客y0k1n0的小破站 本文参考的配置文件信息: AutoencoderKL:stable-diffusion\configs\autoencoder\autoencoder_kl_32x32x4.yaml latent-diffusion:stable-diffusion\configs\latent-diffusion\lsun_churches-ld…...

watchEffect工作原理
watchEffect工作原理 自动依赖收集:watchEffect不需要明确指定要观察的响应式数据,它会自动收集回调函数中用到的所有响应式数据作为依赖。即时执行:watchEffect的回调函数会在组件的setup()函数执行时立即执行一次,以便能够立即…...

斐波那契数列
在 Python 3.11 中实现斐波那契数列的常见方式有多种,下面我将展示几种不同的实现方法,包括递归、迭代和使用缓存(动态规划)来优化递归版本。 1. 递归方式(最简单但效率较低) def fibonacci_recursive(n)…...

TCP并发服务器的实现
一请求一线程 问题 当客户端数量较多时,使用单独线程为每个客户端处理请求可能导致系统资源的消耗过大和性能瓶颈。 资源消耗: 线程创建和管理开销:每个线程都有其创建和销毁的开销,特别是在高并发环境中,这种开销…...

前端大屏自适应方案
一般后台管理页面,需要自适应的也就是大屏这一个,其他的尺寸我感觉用第三方框架继承好的就挺合适的,当然自适应方案也可以同步到所有页面,但我感觉除了 to c 的项目,不太需要所有页面自适应,毕竟都是查看和…...

16.3 k8s容器cpu内存告警指标与资源request和limit
本节重点介绍 : Guaranteed的pod Qos最高在生产环境中,如何设置 Kubernetes 的 Limit 和 Request 对于优化应用程序和集群性能至关重要。对于 CPU,如果 pod 中服务使用 CPU 超过设置的limits,pod 不会被 kill 掉但会被限制。如果没有设置 li…...

【计算机网络 - 基础问题】每日 3 题(二十)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…...

铰链损失函数
铰链损失函数(Hinge Loss)主要用于支持向量机(SVM)中,旨在最大化分类间隔。它的公式为: L ( y , f ( x ) ) max ( 0 , 1 − y ⋅ f ( x ) ) L(y, f(x)) \max(0, 1 - y \cdot f(x)) L(y,f(x))max(0,1−…...

项目实战bug修复
实操bug修复记录 左侧侧边栏切换,再次切换侧边栏,右侧未从顶部初始位置展示。地图定位展示,可跳转到设置的对应位置。一个页面多个el-dialog弹出框导致渲染层级出现问题。锚点滚动定位错位问题。动态类名绑定。el-tree树形通过 draggable 属性…...

Git常用指令整理【新手入门级】【by慕羽】
Git 是一个分布式版本控制系统,主要用于跟踪和管理源代码的更改。它允许多名开发者协作,同时提供了强大的功能来管理项目的历史记录和不同版本。本文主要记录和整理,个人理解的Git相关的一些指令和用法 文章目录 一、git安装 & 创建git仓…...