「动态规划」如何计算能获得多少点数?

2024-06-10 12:44

本文主要是介绍「动态规划」如何计算能获得多少点数?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

740. 删除并获得点数icon-default.png?t=N7T8https://leetcode.cn/problems/delete-and-earn/description/

给你一个整数数组nums,你可以对它进行一些操作。每次操作中,选择任意一个nums[i],删除它并获得nums[i]的点数。之后,你必须删除所有等于nums[i] - 1和nums[i] + 1的元素。开始你拥有0个点数。返回你能通过这些操作获得的最大点数。

  1. 输入:nums = [3,4,2],输出:6,解释:删除4获得4个点数,因此3也被删除。之后,删除2获得2个点数。总共获得6个点数。
  2. 输入:nums = [2,2,3,3,3,4],输出:9,解释:删除3获得3个点数,接着要删除两个2和4。之后,再次删除3获得3个点数,再次删除3获得3个点数。总共获得9个点数。

提示:1 <= nums.length <= 2 * 10^4,1 <= nums[i] <= 10^4。


我们用类似计数排序的思想。定义一个数组arr,arr[i]表示:在nums中,所有点数i的和。如,如果nums = [2,2,3,3,3,4],那么nums = [0,0,4,9,4],意思是:0出现0次,和为0;1出现0次,和为0;2出现2次,和为4;3出现3次,和为9;4出现1次,和为4。

那么,问题就转化为:在nums中选择一些元素,让这些元素的和最大。你不能选择相邻的元素。咦,咋这么眼熟?这不就是打家劫舍嘛!看来小偷又改行来玩游戏了,嘿嘿。我们用动态规划的思想来解决这个问题。

确定状态表示:根据经验和题目要求,我们用dp[i]表示:选到i位置的元素后,此时的最大和。再细分为:

  • 用f[i]表示:必须选择i位置的元素后,此时的最大和
  • 用g[i]表示:不能选择i位置的元素后,此时的最大和

推导状态转移方程:分别讨论2种情况中,最近的一步,即是否选择i - 1位置的元素。

  • 考虑f[i]。如果选择i位置的元素,那么就不能选择i - 1位置的元素。选择完i位置的元素之后的最大和,就等于不能选择i - 1位置的元素之后的最大和加上i位置的元素,即f[i] = g[i - 1] + arr[i]。
  • 考虑g[i]。如果不能选择i位置的元素,那么此时的最大和就等于考虑完i - 1元素之后的最大和。由于不确定是否选择i - 1位置的元素,所以不能选择i位置的元素后的最大和,就等于是否选择i - 1位置的元素这2种情况的最大和的较大值,即g[i] = max(f[i - 1], g[i - 1])。

综上所述:f[i] = g[i - 1] + arr[i],g[i] = max(f[i - 1], g[i - 1])

初始化:根据状态转移方程,在计算f[0]和g[0]时会越界,所以要对其初始化。

  • f[0]表示:必须选择0位置的元素之后,此时的最大和,显然f[0] = arr[0]。
  • g[0]表示:不能选择0位置的元素之后,此时的最大和,显然g[0] = 0。

综上所述:f[0] = arr[0],g[0] = 0

填表顺序:根据状态转移方程,f[i]依赖于g[i - 1],g[i]依赖于f[i - 1]和g[i - 1],所以应从左往右同时填f表和g表

返回值:假设arr数组有n个元素。最终要返回考虑完n - 1位置的元素后,此时的最大和。由于并不确定是否选择n - 1位置的元素,再根据状态表示,我们应返回的是,是否选择n - 1位置的元素这2种情况中,最大和的较大值,即max(f[n - 1], g[n - 1])

细节问题:由于f表和g表的下标范围是[0, n - 1],所以规模都是1 x n

时间复杂度:O(N),空间复杂度:O(N)。

class Solution {
public:int deleteAndEarn(vector<int>& nums) {const int N = 10001;// 转化问题vector<int> arr(N);for (auto num : nums) {arr[num] += num;}// 创建dp表vector<int> f(N);auto g = f;// 初始化f[0] = arr[0];// 填表for (int i = 1; i < N; i++) {f[i] = g[i - 1] + arr[i];g[i] = max(f[i - 1], g[i - 1]);}// 返回结果return max(f[N - 1], g[N - 1]);}
};

这篇关于「动态规划」如何计算能获得多少点数?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048199

相关文章

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

SpringBoot实现Kafka动态反序列化的完整代码

《SpringBoot实现Kafka动态反序列化的完整代码》在分布式系统中,Kafka作为高吞吐量的消息队列,常常需要处理来自不同主题(Topic)的异构数据,不同的业务场景可能要求对同一消费者组内的... 目录引言一、问题背景1.1 动态反序列化的需求1.2 常见问题二、动态反序列化的核心方案2.1 ht

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模