【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 x1 x + 1 x+1 x+1 也会从数组中删除。问题要求的是:你通过删除数字获得的最大点数是多少?

2. 理解问题和递推关系:

这个问题类似于"打家劫舍"问题,可以转化为一个动态规划问题。每次删除某个数字时,你既获得了它的值,也会让相邻的数字无法再被选择。因此,可以把问题转化为:每个数 x x x 要么选择,要么跳过。

我们将问题理解为两个选择:

  1. 选择删除某个数字 x x x :那么你会获得 x x x 出现的总值 x x x *出现次数,同时不能再选择 x − 1 x-1 x1 x + 1 x+1 x+1
  2. 不选择删除某个数字 x x x :那么你可以选择去考虑删除其他数字。

为了将问题转化成打家劫舍的形式:

  1. 我们可以对 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 出现次数。
  2. 现在,问题转化为:给定一个数组 e a r n [ ] earn[] earn[],从中选择不相邻的数,使得获得的总和最大。这就是"打家劫舍"问题的典型形式。

3. 解决方法:

  1. 预处理:首先统计 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 出现次数。
  2. 递推公式:我们使用动态规划来解决该问题,设 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[i1],dp[i2]+earn[i])

解释:

  • d p [ i − 1 ] dp[i-1] dp[i1] 表示我们不删除数字 i i i,因此直接继承前面的最大值。
  • d p [ i − 2 ] + e a r n [ i ] dp[i-2] + earn[i] dp[i2]+earn[i] 表示我们删除了数字 i i i,因此需要加上 e a r n [ i ] earn[i] earn[i],同时要跳过 i − 1 i-1 i1
  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[i1] 和 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 代码解释

  1. 边界条件:如果 n u m s [ ] nums[] nums[] 为空,直接返回 0 0 0
  2. 统计:我们遍历 n u m s [ ] nums[] nums[],构建 e a r n [ ] earn[] earn[],其中 e a r n [ x ] = x ∗ earn[x] = x * earn[x]=x 出现次数。
  3. 动态规划:通过 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++ 代码解释

  1. 边界条件:如果 n u m s [ ] nums[] nums[] 为空,直接返回 0 0 0
  2. 统计:构建 e a r n [ ] earn[] earn[] 数组,存储每个数字的总收益。
  3. 动态规划:使用两个变量 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

总结:

  • 动态规划是解决此类问题的核心,将删除数字及其邻居的问题转化为典型的选择不相邻数的问题。
  • 优化空间:通过使用常量空间,减少了数组存储的开销,使得算法在时间和空间上都更高效。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

DownShift: Tuning Shift Reduction With Reliability for Racetrack Memories

目录 DownShift: Tuning Shift Reduction With Reliability for Racetrack Memories文章摘要:文章的主要贡献包括:文章的结构如下:DownShiftDownShift通过以下方式改进了现有的数据放置策略: GROGU(Generating Reliabi…

2024最受欢迎的3款|数据库管理和开发|工具

1.SQLynx(原SQL Studio) 概述: SQLynx是一个原生基于Web的SQL编辑器,由北京麦聪软件有限公司开发。它最初被称为SQL Studio,后改名为SQLynx,支持企业的桌面和Web数据库管理。SQLynx支持所有流行的数据库&a…

工业一体机实现接口与模块选配

在现代工业自动化和智能制造的浪潮中,工业一体机因其集成化、稳定性高和适应性强的特性而逐渐成为企业生产过程中不可或缺的设备。为了满足不同客户的需求,工业一体机的接口与模块选配功能显得尤为重要。 一、工业一体机的基本概念 工业一体机是将计算、…

跟着B战学习JAVA面试八股文

学习链接:https://www.bilibili.com/video/BV1gm411S7EX/?spm_id_from333.337.search-card.all.click&vd_sourceefbaa07876b231ae3225ba8999116807 创建线程的几种方式? 继承Thread类实现Runnable接口实现Callable接口通过线程池来创建线程 为什么…

【官方Mamba库】原理简述和代码解析

目录 1 代码原理简述1.1 原始结构——SSM1.2 结构改进——S4(Structured State Space for Sequences)1.2.1 离散化1.2.2HiPPO 1.3 最终版本——Mamba(又称S6或selective SSMs) 2 代码库目录结构2.1 mamba_simple.py主体结构2.1.1 …

OLED(2)驱动篇

文章目录 1 概述2 代码简述2.1 OLED 对象2.2 OLEDProtocol 对象2.3 OLEDFont 对象 3 成果展示 1 概述 1)代码仓库:这里尝试了两种面向对象的方式,不足之处敬请指正。 OOP 方式:https://gitee.com/luyaocf/demo-jlc_stm32f407_oop.…

Unity 设计模式 之 行为型模式-【命令模式】【责任链模式】

Unity 设计模式 之 行为型模式-【命令模式】【责任链模式】 目录 Unity 设计模式 之 行为型模式-【命令模式】【责任链模式】 一、简单介绍 二、命令模式(Command Pattern) 1、什么时候使用命令模式 2、使用命令模式的好处 3、使用时的注意事项 三…

FME学习笔记

读取数据 方法一:add reader 通过读模块来进行数据的读取 方法二:FeatureReader Parameters 通过转换器来进行数据的读取 可以通过空间范围进行筛选 在FME中,所有数据处理都要用到的,绝对的重点:转换器&#xff…

【Python】PyCharm: 强大的 Python 开发环境

⭕️宇宙起点 📢 引言🎬 什么是 PyCharm?🔨 PyCharm 的核心特性1. 智能代码编辑2. 调试和测试3. 项目和代码结构导航4. 集成 AI 助手5. 远程开发6. 集成数据库7. 科学工具8. 版本控制集成9. Web 开发 📦 安装 PyCharm&…

黑马智数Day4-1

新增月卡 配置路由完成跳转 {path: /cardAdd,component: () > import(/views/car/car-card/add-card) }<el-button type"primary" click"$router.push(/cardAdd)">添加月卡</el-button> 车辆信息表单验证 <el-form :model"carInf…

Bug:ThreadPoolTaskScheduler搭配CronTask完成定时任务,关闭scheduler后CronTask任务仍然执行?

【问题】执行下面代码后&#xff0c;关闭ThreadPoolTaskScheduler&#xff0c;CronTask仍然继续执行。 Configuration public class config {Beanpublic String getString() throws InterruptedException {Runnable runnable () -> {try {System.out.println("hello r…

《程序猿之设计模式实战 · 适配器模式》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

【后端开发】JavaEE初阶—线程安全问题与加锁原理(超详解)

前言&#xff1a; &#x1f308;上期博客&#xff1a;【后端开发】JavaEE初阶—Theard类及常见方法—线程的操作&#xff08;超详解&#xff09;-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f308;小编会在后端开发的学习中不…

关于javascript中防抖和节流的使用详解

防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常见的优化技巧&#xff0c;通常用于控制函数在短时间内频繁触发的场景&#xff0c;尤其是在处理用户输入、滚动、窗口大小调整等事件时。它们的主要目的是减少不必要的函数调用&#xff0c;…

超详细超实用!!!AI编程之cursor编写设计模式开闭原则实例(四)

云风网 云风笔记 云风知识库 一、设计模式开闭原则定义 当应用的需求改变时&#xff0c;在不修改软件实体&#xff08;项目模块、类、接口方法&#xff09;的源代码或者二进制代码的前提下&#xff0c;可以扩展模块的功能&#xff0c;使其满足新的需求。即软件实体应当对扩展开…

【Linux】nginx连接前端项目

文章目录 一、项目编译1.编译文件2.dist文件 二、Linux nginx配置三、启动nginx 一、项目编译 1.编译文件 2.dist文件 二、Linux nginx配置 在Xshell软件中&#xff0c;点击CtrlAltF进入文件传输找到地址&#xff1a;/usr/local/nginx/html将dist文件传入 找到nginx.conf&…

git add成功后忘记commit的文件丢了?

本文目标&#xff1a;开发人员&#xff0c;在了解git fsck命令用法的条件下&#xff0c;进行git add成功但由于误操作导致丢失的文件找回&#xff0c;达到找回丢失文件的程度。 文章目录 1 痛点2 解决方案3 总结/练习 1 痛点 开发过程中&#xff0c;分支太多&#xff08;基线分…

CREO教程——2 绘制标准图纸

CREO教程——2 绘制标准图纸 说明&#xff1a;继承第一章设置好的配置文件&#xff0c;这一章进行学习分享如何定制自己的图纸图框&#xff0c;参考国家标准距&#xff0c;定制属于设计师或单位的通用图框。 1.设置工作目录 1.1设置工作目录 1.打开软件设置工作目录&#x…

u盘格式化怎么恢复数据?四款工具来救急!

工作中真的没少碰到过那些让人头疼的数据丢失问题&#xff0c;特别是U盘里的宝贝数据一不小心就“蒸发”了&#xff0c;简直让人欲哭无泪。不过别担心&#xff0c;我作为一个数据恢复的新手小白&#xff0c;最近可是亲测了几款超给力的数据恢复软件&#xff0c;今天就来跟大家分…

19c-TNS-12541: TNS:no listener

有套19c单机&#xff0c;没应用任何的补丁&#xff0c;使用lsnrctl status查看监听是异常的&#xff0c;但是lsnrctl start发现监听已运行&#xff0c;当前业务连接都正常&#xff0c; orcl:/home/oracledb> lsnrctl status LSNRCTL for Linux: Version 19.0.0.0.0 - Pro…