首页 > 其他分享 >力扣刷题——3177. 求出最长好子序列 II

力扣刷题——3177. 求出最长好子序列 II

时间:2024-09-09 17:28:12浏览次数:1  
标签:力扣 遍历 好子 nums int II vector temVec dp

根据题意,暴力做法不可取,因为至少要对遍历位置之前的位置,以及不同的子序列阈值(跟k对应的那个)做循环。于是就能够想到使用动态规划的手段去解决问题,考虑需要保存的两个状态,当前序列末尾的数字、子序列阈值,设计一个二维的dp数组dp[i][j],其中i为位置索引,指代当前在nums数组中遍历的位置,j则为子序列阈值。
综上,每次循环递推有如下递推式:
nums[x] != nums[i]并且j > 0时,dp[i][j] = max(dp[x][j - 1] + 1, dp[i][j])
nums[x] == nums[i]时,dp[i][j] = dp[x][j] + 1
每次循环枚举所有可能的j值,即0 <= j <= k,以及所有可能的x值,即0 <= x < i。则有实现代码如下:

class Solution
{
public:
    int maximumLength(vector<int> &nums, int k)
    {
        int n = nums.size();
        vector<vector<int>> dp(n, vector<int>(k + 1, -1));
        int res = 1;
        for (int i = 0; i < n; i++)
        {
            dp[i][0] = 1;
            for (int j = 0; j <= k; j++)
            {
                for (int x = 0; x < i; x++)
                {
                    if (nums[i] == nums[x])
                    {
                        dp[i][j] = max(dp[i][j], dp[x][j] + 1);
                    }
                    else
                    {
                        if (j)
                        {
                            dp[i][j] = max(dp[x][j - 1] + 1, dp[i][j]);
                        }
                    }
                    res = max(res, dp[i][j]);
                }
            }
        }
        return res;
    }
};

但是这样仍然会超时。想到因为dp数组之中的第一维度信息只跟具体的数值有关,跟数值的位置无关,使用哈希表可以减少需要遍历的数据范围,因此有以下实现:

class Solution
{
public:

    int maximumLength(vector<int> &nums, int k)
    {
        int n = nums.size();
        int res = 1;
        unordered_map<int, vector<int>> dp;
        for (int i = 0; i < n; i++)
        {
            vector<int> temVec;
            if (dp.find(nums[i]) == dp.end())
            {
                temVec = vector<int>(k + 1, 0);
                temVec[0] = 1;
            }
            else
            {
                temVec = dp[nums[i]];
            }

            for (auto tem : dp)
            {
                for (int j = 0; j <= k; j++)
                {
                    if (nums[i] == tem.first)
                    {
                        if (dp[tem.first][j])
                            temVec[j] = max(temVec[j], dp[tem.first][j] + 1);
                        res = max(res, temVec[j]);
                    }
                    else
                    {
                        if (j)
                        {
                            if (dp[tem.first][j - 1])
                                temVec[j] = max(dp[tem.first][j - 1] + 1, temVec[j]);
                        }
                    }
                    res = max(res, temVec[j]);
                }
            }
            dp[nums[i]] = temVec;
        }
        return res;
    }
};

结果还是超时。。。使用哈希表,对当nums[x] == nums[i]的情况下优化了计算量,然而还存在大量nums[x] != nums[i]的情况。
实际上对于这种情况,可以绕过重复遍历nums[x]。当遍历到i位置时,如果后面的位置不存在nums[x],并且dp[nums[x]]中的值均不是目前的最优解,那么可以判断由dp[nums[x]]递推出的值不可能会是最终的答案;假如后面的位置存在nums[x],那么仍然可以通过维护dp[nums[x]],保留可能的递推来源。
基于上面这个想法,可以选择开一个数组,单独维护当nums[x] != nums[i]时的最优解,这样就意味着,用基于这个辅助数组递推出来的解可能是最优的,实现代码如下:

class Solution {
public:
    int maximumLength(vector<int> &nums, int k)
    {
        int n = nums.size();
        int res = 1;
        vector<int> sub(k + 1, 0);
        unordered_map<int, vector<int>> dp;
        for (int i = 0; i < n; i++)
        {
            vector<int> temVec;
            if (dp.find(nums[i]) == dp.end())
            {
                temVec = vector<int>(k + 1, 0);
            }
            else
            {
                temVec = dp[nums[i]];
            }

            for (int j = 0; j <= k; j++)
            {
                temVec[j]++;
                if(j)
                {
                    temVec[j] = max(temVec[j], sub[j - 1] + 1);
                }
            }
            dp[nums[i]] = temVec;

            for(int j = 0; j <= k; j++)
            {
                sub[j] = max(sub[j], dp[nums[i]][j]);
                res = max(res, sub[j]);
            }
                
        }
        return res;
    }
};

标签:力扣,遍历,好子,nums,int,II,vector,temVec,dp
From: https://www.cnblogs.com/yuhixyui/p/18404195

相关文章

  • IIS 屏蔽Help页面和Swagger
    1、MVC屏蔽HelP页面暴露API接口方法:找到目录下的 Areas\HelpPage\Views\Help的Index.cshtml注释如代码中@[email protected]@usingSystem.Web.Http.Description@[email protected]......
  • 今日算法随笔:填充每个节点的下一个右侧节点指针 II
    题目链接:117.填充每个节点的下一个右侧节点指针II题目描述给定一个二叉树,填充它的每个next指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将next指针设置为NULL。初始状态下,所有next指针都被设置为NULL。示例:输入:root=[1,2,3,4,5,null,7]输出:[......
  • 一文讲清,常用通信协议IIC,SPI,串口,基于STM32
    目录一、通讯的基本概念1.串行通讯2.并行通讯3.传输模式(单工、半双工、全双工)二、常见通讯协议(串口、IIC、SPI)1.串口(1)UART和USART的区别是什么?(2)UART(TTL、RS232、RS485)(3)基于STM32的HAL库的串口配置2.IIC(1)物理层(2)协议层(3)软件模拟IIC通讯代码(4)有关IIC面试的问题(5)硬......
  • Java毕设项目II基于Spring Boot的在线远程考试系统设计与实现
    目录一、前言二、技术介绍三、系统实现四、论文参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言随着信息技术的飞速发展和教育模式的不断......
  • 142. 环形链表 II
    给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。......
  • Day07 字符串part01| LeetCode 344. 反转字符串,541. 反转字符串II,卡码网:54.替换数字
    反转字符串344.反转字符串classSolution{publicvoidreverseString(char[]s){intlens=s.length;intright,left;if(lens%2!=0)//奇数个{right=lens/2+1;left=lens/2-1......
  • Day04 链表part02| LeetCode 24. 两两交换链表中的节点,19. 删除链表的倒数第 N 个,160.
    两两交换链表中的节点24.两两交换链表中的节点classSolution{publicListNodeswapPairs(ListNodehead){//设置虚拟头节点ListNodedummy=newListNode(0,head);ListNodecur=dummy;while(cur.next!=null&......
  • LeetCode //C - 350. Intersection of Two Arrays II
    350.IntersectionofTwoArraysIIGiventwointegerarraysnums1andnums2,returnanarrayoftheirintersection.Eachelementintheresultmustappearasmanytimesasitshowsinbotharraysandyoumayreturntheresultinanyorder. Example1:......
  • 代码随想录算法训练营第九天 | Javascript | 力扣Leetcode | 手撕KMP的一天 | 28. 找
    目录前言简介题目链接:28.找出字符串中第一个匹配项的下标题目链接:459.重复的子字符串前言踏平坎坷成大道,斗罢艰险又出发!自律的尽头是自控,自控的尽头是硬控。愿道友们披荆斩棘,终能得偿所愿。简介本人是小几年经验的前端开发,算法基础只有力扣几十道题,非常薄弱。......
  • Java毕设项目II基于Spring Boot+Vue的失物招领平台
    目录一、前言二、技术介绍三、系统实现四、论文参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言在快节奏的生活中,物品遗失与寻回成为了人......