【LeetCode】动态规划—673. 最长递增子序列的个数(附完整Python/C++代码)

news2024/12/24 9:06:23

动态规划—673. 最长递增子序列的个数

  • 前言
  • 题目描述
  • 基本思路
    • 1. 问题定义
    • 2. 理解问题和递推关系
    • 3. 解决方法
      • 3.1 动态规划方法
      • 3.2 优化方法
    • 4. 进一步优化
    • 5. 小总结
  • 代码实现
    • Python
      • Python3代码实现
      • Python 代码解释
    • C++
      • C++代码实现
      • C++ 代码解释
        • 1. 初始化:
        • 2. 动态规划过程:
        • 3. 计算结果:
  • 总结:

前言

在算法研究中,序列问题是一个常见而重要的主题。最长递增子序列问题不仅在理论上具有挑战性,同时在许多实际应用中也非常有用,如数据分析、动态规划和计算机视觉等领域。本文将深入探讨如何利用动态规划和计数技巧来解决该问题,同时提供 Python 和 C++ 的具体实现,以帮助读者更好地理解和掌握这一算法。

题目描述

在这里插入图片描述

基本思路

1. 问题定义

给定一个整数数组 nums,我们需要找到其中最长的递增子序列的长度,以及该长度的递增子序列的个数。

2. 理解问题和递推关系

  • 最长递增子序列(LIS)是指在数组中选择若干元素,使得它们的顺序与原数组相同,且毎个元素都大于前一个元素。

・ 定义 dp[i] 为以 nums[i] 结尾的最长递增子序列的长度, count[i] 为以 nums[i] 结尾的最长递增子序列的个数。

・递推关采如下:
・对于每个 nums[i],音看其前面的所有元素 nums[j]( j < i )

  • 如果 nums[j] < nums[i], 则更新 dp[i] :

d p [ i ] = max ⁡ ( d p [ i ] , d p [ j ] + 1 ) d p[i]=\max (d p[i], d p[j]+1) dp[i]=max(dp[i],dp[j]+1)

  • 更新 count[i]:
  • 如果 d p [ j ] + 1 > d p [ i ] d p[j]+1>d p[i] dp[j]+1>dp[i] ,说明找到了一个更长的递增子序列,更新 count[i]count[j]
  • 如果 d p [ j ] + 1 = = d p [ i ] d p[j]+1==d p[i] dp[j]+1==dp[i] ,说明找到了一个同样长度的递增子序列,累加 count[j]count[i]

3. 解决方法

3.1 动态规划方法

  1. 初始化两个数组 d p d p dpcount, 长度与 nums 相同:
    • dp[i] 初始化为 1,因为每个元素本身可以形成长度为 1 的递增子序列。
    • count[i]初始化为 1 ,因为毎个元素自身的子序列个数为 1
  2. 使用双重矿环遍历数组 nums,更新 dp[i]count[i]数组。
  3. 最终,找到 max ⁡ ( d p ) \max (\mathrm{dp}) max(dp) 来获取最长递增子序列的长度,并对 count 数组进行遍历,累加所有 count[i] (当 dp[i] 等于最长长度) 以获得该长度子序列的个数。

3.2 优化方法

  • 使用二分查找技术可以进一步优化 d p d p dp 数组的构建,使时间复杂度降低到 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 通过维护一个数组 tails 来记录当前长度的递增子序列的末尾元素,从而更新 count

4. 进一步优化

  • 利用 bisect 库可以方便地在 tails 中找到合适的位置,并更新计数,进一步提高效率。

5. 小总结

  • 本文通过动态规划方法有效解决了计算最长递增子序列及其个数的问题。
  • 该问题展示了动态规划与计数相结合的技巧,适用于类似的序列问题。

以上就是最长递增子序列的个数问题的基本思路。

代码实现

Python

Python3代码实现

class Solution:
    def findNumberOfLIS(self, nums):
        if not nums:
            return 0

        n = len(nums)
        dp = [1] * n  # 初始化 dp 数组
        count = [1] * n  # 初始化 count 数组

        for i in range(n):  # 遍历每个元素
            for j in range(i):  # 检查前面的元素
                if nums[j] < nums[i]:  # 如果找到较小的元素
                    if dp[j] + 1 > dp[i]:  # 找到更长的递增子序列
                        dp[i] = dp[j] + 1
                        count[i] = count[j]  # 更新个数
                    elif dp[j] + 1 == dp[i]:  # 找到相同长度的递增子序列
                        count[i] += count[j]  # 累加个数

        max_length = max(dp)  # 获取最长递增子序列的长度
        return sum(count[i] for i in range(n) if dp[i] == max_length)  # 返回该长度的个数

Python 代码解释

  • 初始化:创建 dpcount 数组,分别存储最长递增子序列的长度和个数。
  • 双重循环:外层循环遍历每个元素,内层循环检查之前的元素,更新 dpcount 数组。
  • 返回结果:找到 max(dp),然后累加所有 count[i](当 dp[i] 等于最大长度)以获得结果。

C++

C++代码实现

class Solution {
public:
    int findNumberOfLIS(vector<int>& nums) {
        if (nums.empty()) return 0;

        int n = nums.size();
        vector<int> dp(n, 1);  // dp[i] 表示以 nums[i] 结尾的最长上升子序列的长度
        vector<int> count(n, 1);  // count[i] 表示以 nums[i] 结尾的最长上升子序列的个数
        int max_length = 0;  // 记录最长上升子序列的长度
        int max_count = 0;   // 记录最长上升子序列的个数

        // 动态规划计算 dp 和 count 数组
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (nums[i] > nums[j]) {
                    if (dp[j] + 1 > dp[i]) {
                        dp[i] = dp[j] + 1;  // 更新长度
                        count[i] = count[j]; // 更新个数
                    } else if (dp[j] + 1 == dp[i]) {
                        count[i] += count[j]; // 追加个数
                    }
                }
            }
            max_length = max(max_length, dp[i]); // 更新最大长度
        }

        // 计算最长上升子序列的总个数
        for (int i = 0; i < n; ++i) {
            if (dp[i] == max_length) {
                max_count += count[i]; // 统计个数
            }
        }

        return max_count; // 返回结果
    }
};

C++ 代码解释

1. 初始化:
  • dp[i] 用于存储以 nums[i] 结尾的最长上升子序列的长度。
  • count[i] 用于存储以 nums[i] 结尾的最长上升子序列的个数。
  • max_lengthmax_count 分别用于记录最长上升子序列的长度和个数。
2. 动态规划过程:
  • 外层循环遍历每个元素 i,内层循环遍历 i 之前的所有元素 j
  • 如果 nums[i] 大于 nums[j],检查是否形成了更长的上升子序列。
  • 如果找到了更长的序列,更新 dp[i]count[i];如果找到了相同长度的序列,增加 count[i]
3. 计算结果:
  • 遍历 dp 数组,统计最长上升子序列的总个数。

总结:

  • 本文通过对最长递增子序列及其个数问题的深入分析,展示了动态规划的强大能力。
  • 结合计数的技巧,使得解决方案不仅有效且易于理解,适合解决类似的复杂问题。

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

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

相关文章

Basic Pentesting靶机打靶记录

一、靶机介绍 下载链接&#xff1a;https://download.vulnhub.com/basicpentesting/basic_pentesting_1.ova 二、信息收集 确认靶机ip&#xff1a;192.168.242.136 arp-scan -l 扫描端口 nmap -p- -A -sS 192.168.242.136 这里开放了21&#xff0c;22&#xff0c;80端口 扫…

美发店数字化转型:SpringBoot管理系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

鸿蒙开发:文件推送到沙箱路径

最近一个项目需要基于沙箱路径下的文件进行操作&#xff0c;奈何应用沙箱路径下没有。找来找去方法都是要把文件推送进去。以下是我的一些拙见&#xff0c;请各位看官老爷指点一二。 沙箱路径 沙箱路径&#xff08;Sandbox Path&#xff09;通常是指在计算机安全和软件开发中…

【大学学习-大学之路-回顾-电子计算机相关专业-学习方案-自我学习-大二学生(2)】

【大学学习-大学之路-回顾-电子&计算机相关专业-学习方案-自我学习-大二学生&#xff08;2&#xff09;】 1、前言2、总体说明1-保证课程原因1&#xff1a;原因2&#xff1a; 2-打比赛3-自我适应 - 享受大学生活 3、 保证课程1、英语课程2、专业课程3、其他课程 4、 打比赛…

数据质量指标:如何衡量数据的准确性

数据质量是任何数据驱动运营的重要组成部分。即使对于不打算将数据集出售给其他公司的企业&#xff0c;数据的质量和准确性也会极大地影响决策效率。 不幸的是&#xff0c;没有单一指标可以确保数据质量达到标准。您必须跟踪多个指标并不断关注它们。因此&#xff0c;维护数据…

高通QCS6490开发(十):合并显示多路安防摄像头

视频分析时边缘侧AI应用的一个常见场景&#xff0c;边缘侧的单个节点能够同时视频流越多&#xff0c;这不仅提高了处理效率&#xff0c;还具有显著的经济性。本文将介绍如何使用QCS6490的VPU&#xff08;视频处理单元&#xff09;来支持H264/H265的视频硬件编解码&#xff0c;并…

C语言计算GPS卫星位置

1 概述 在用GPS信号进行导航定位以与制订观测计划时&#xff0c;都必须已知GPS卫星在空间的瞬间位置。卫星位置的计算是根据卫星电文所提供的轨道参数按一定的公式计算的。本节专门讲解观测瞬间GPS卫星在地固坐标系中坐标的计算方法。 2 卫星位置的计算 1. 计算卫星运行的平…

如何做好项目管理中的需求管理?

本人任职于某科技公司项目经理&#xff0c;主要帮助客户梳理现有的业务流程&#xff0c;借助公司自主研发的低代码平台实现流程的线上化&#xff0c;业务的数字化转型。 由于项目性质特殊&#xff0c;在实施期间&#xff0c;对于总体项目需要采用传统的瀑布式开发规划整个项目…

揭秘网络流量分析的秘密 WireShark使用教程

WireShark是一个网络包分析工具。该工具主要用来捕获网络数据包&#xff0c;并自动解析网络数据包&#xff0c;为用户显示数据包详细信息&#xff0c;供用户对数据包进行分析 网络管理员 使用WireShark来检查网络问题网络安全工程师 使用WireShark来检查咨询安全相关问题开发人…

腾讯云大牛亲码“redis深度笔记”在牛客网上火了,完整 PDF 开源

前言 作为这个时代码代码的秃头人员&#xff0c;对Redis肯定是不陌生的&#xff0c;如果连Redis都没用过&#xff0c;还真不好意思出去面试&#xff0c;指不定被面试官吊打多少次。 毕竟现在互联网公司和一些创业公司都要用到Redis&#xff0c;像亚马逊、谷歌、阿里、腾讯都要…

【大模型理论篇】精简循环序列模型(minGRU/minLSTM)性能堪比Transformer以及对循环神经网络的回顾

1. 语言模型之精简RNN结构 近期关注到&#xff0c;Yoshua Bengio发布了一篇论文《Were RNNs All We Needed?》&#xff0c;提出简化版RNN&#xff08;minLSTM和minGRU&#xff09;。该工作的初始缘由&#xff1a;Transformer 在序列长度方面的扩展性限制重新引发了对可在训练期…

6款支持多平台的电脑监控软件,电脑多屏监控软件

在当今信息化办公环境中&#xff0c;监控软件已成为企业提升工作效率、管理公司资源的关键工具。随着远程办公与多设备管理的兴起&#xff0c;具备多平台兼容性和强大功能的电脑监控软件&#xff0c;能够帮助管理者随时掌握员工的工作情况、数据安全以及企业运营状态。本文将推…

【全解析】从xinput1_3.dll的作用到解决xinput1_3.dll相关问题的深度探究

在计算机系统的运行过程中&#xff0c;我们有时会遇到各种各样的文件缺失问题&#xff0c;其中xinput1_3.dll文件的缺失是比较常见的一种情况。今天这篇文章将和大家聊聊从xinput1_3.dll的作用到解决xinput1_3.dll相关问题的深度探究&#xff0c;将电脑恢复正常。 xinput1_3.dl…

SROP验证

文章目录 SROPsignal机制 SROP的利用原理&#xff1a;获取shellsystem call chains条件&#xff1a;sigreturn 测试 例题&#xff1a; SROP signal机制 signal 机制是类 unix 系统中进程之间相互传递信息的一种方法。一般&#xff0c;我们也称其为软中断信号&#xff0c;或者软…

Flash 闪存技术基础与 SD NAND Flash 产品测试解析

本篇除了对flash闪存进行简单介绍外&#xff0c;另给读者推荐一种我本人也在用的小容量闪存。 自带坏块管理的SD NAND Flash&#xff08;贴片式TF卡&#xff09;&#xff0c;尺寸小巧&#xff0c;简单易用&#xff0c;兼容性强&#xff0c;稳定可靠&#xff0c;标准SDIO接口&a…

产品图册不会设计?这个网站有大量产品图册案例和模板。

​在当今这个视觉至上的时代&#xff0c;一本设计精美的产品图册无疑能为企业或个人品牌增色不少。产品图册不仅能直观地展示产品特点&#xff0c;还能传达品牌理念&#xff0c;从而吸引潜在客户。然而&#xff0c;对于很多企业或个人来说&#xff0c;设计一本专业水准的产品图…

10月10日

hh 绘制 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QMouseEvent> #include<QPaintEvent> #include<QPixmap> #include<QPainter> #include<QPen> #include<QColorDialog> QT_BEGIN_NAMESPACE namespace Ui {…

“ORA-01017(:用户名/口令无效; 登录被拒绝)”解决办法

目录 报错&#xff1a;ORA-01017&#xff08;&#xff1a;用户名/口令无效; 登录被拒绝&#xff09; 1.打开CMD命令窗&#xff0c;输入sqlplus / as sysdba 1&#xff09;修改密码 SQL>alter user 用户名 identified by 密码 alter user system identified by manager;2&…

27.数据结构与算法-图的遍历(DFS,BFS)

遍历定义与遍历实质 图的特点 图的常用遍历方法 深度优先搜索-DFS 邻接矩阵表示的无向图深度遍历实现 DFS算法效率分析 非连通图的遍历 广度优先搜索遍历-BFS 邻接表表示的无向图广度遍历实现 BFS算法效率分析 非连通图的广度遍历 DFS和BFS算法效率比较

多线程-初阶(2)BlockingQueueThreadPoolExecutor

学习目标&#xff1a; 熟悉wait和notify的线程休眠和启动 熟悉多线程的基本案例 1.单例模式的两种设置模式:懒汉模式和饿汉模式 2.阻塞队列(生产者消费者模型) 3.线程池 4.定时器 1.wait和notify 由于线程之间是抢占式执⾏的, 因此线程之间执⾏的先后顺序难以预知. 但是…