当前位置:首页 > 牛客 > 【牛客4456题解析】最长上升子序列的动态规划+二分查找解法

【牛客4456题解析】最长上升子序列的动态规划+二分查找解法

1天前

【牛客4456题解析】最长上升子序列的动态规划+二分查找解法 最长上升子序列 动态规划 二分查找 牛客题解 C++ 第1张

一、题目解读

牛客4456题要求在一个整数序列中寻找最长上升子序列(LIS)的长度。题目考察的核心是动态规划与高效查找算法的结合,需要设计一种能在给定序列中快速找到最长递增子序列的方法,通常需要平衡时间复杂度和代码简洁性。

二、解题思路

采用动态规划(DP)结合二分查找实现LIS求解。核心思想是:维护一个递增序列dp,每次遍历输入序列A中的元素num,通过lower_bound找到dp中第一个不小于num的位置。若未找到(即num比dp所有元素大),则扩展dp;否则替换该位置元素。由于dp始终递增,其长度即为LIS长度。此优化将时间复杂度从O(N^2)降至O(NlogN)。

三、解题步骤

1. 初始化:创建动态规划数组dp,用于存储递增子序列

2. 遍历输入序列:

○ 对每个元素num,使用lower_bound在dp中查找第一个≥num的位置it。

○ 若it为dp末尾(即num比dp所有元素大),则执行dp.push_back(num),扩展序列。

○ 否则,替换it位置的元素(*it = num),确保dp保持递增且长度最短(因LIS长度相同,但末尾元素更小,后续可容纳更多元素)。

3. 返回结果:dp的长度即为最长上升子序列的长度。

四、代码和注释

class AscentSequence {
  public:
    int findLongest(vector<int> A, int n) {
        vector<int> dp; // 维护一个递增序列
        for (int num : A) { // 遍历输入序列
            // 使用lower_bound找到第一个不小于当前元素的位置
            auto it = lower_bound(dp.begin(), dp.end(), num);
            if (it == dp.end()) { // 未找到(num比dp所有元素大)
                dp.push_back(num); // 扩展序列
            } else { // 找到替换位置
                *it = num; // 替换第一个≥num的元素,保持dp递增
            }
        }
        return dp.size(); // 最终序列长度即为LIS长度
    }
};

五、总结

本解法通过动态规划结合二分查找,将LIS问题的时间复杂度优化至O(NlogN),显著提升效率。关键在于利用递增序列dp的特性,通过替换操作确保其“紧凑性”,从而在查找时可用lower_bound快速定位。该思路不仅适用于面试算法题,也为处理大规模数据的LIS问题提供了实用策略,是动态规划与高级算法结合的典型案例。

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣740.删除并获得点数 预处理与动态规划的巧妙融合

力扣740.删除并获得点数 预处理与动态规划的巧妙融合

题意解析:给定一组数字,每当你选择一个数字x时,所有等于x-1和x+1的数字都会被自动移除。你需要通过巧妙的选择顺序,最大化获得的点数总和。这个问题可以转化为对离散化数字分布的动态规划问题——将相邻数...

【深度优先搜索实战】力扣547题:省份数量问题的图论解法

【深度优先搜索实战】力扣547题:省份数量问题的图论解法

题目解读‌我们面对的是一个典型的图论问题:给定一个城市的连接矩阵,需要计算其中相互连通的城市群(省份)数量。这个问题可以抽象为无向图中的连通分量计算,每个城市代表图中的一个节点,城市之间的连接关系代表...

征服力扣704题:三步掌握经典二分查找算法

征服力扣704题:三步掌握经典二分查找算法

题目重解我们面对的是算法领域最经典的二分查找问题:在一个已排序的整数数组中,快速定位目标值的位置。就像在一本按字母顺序排列的字典中查找单词,我们不需要逐页翻阅,而是通过不断折半的方式快速缩小搜索范围,...

力扣第654题:最大二叉树解题教程 用数组构造最大二叉树

力扣第654题:最大二叉树解题教程 用数组构造最大二叉树

题目解读给定一个不含重复元素的整数数组,我们需要构建一棵最大二叉树。构建规则是:数组中的最大值作为根节点,其左侧子数组构建左子树,右侧子数组构建右子树,然后递归地应用这个规则。这种构建方式体现了分治思...

力扣933题:队列的妙用:如何高效统计最近请求

力扣933题:队列的妙用:如何高效统计最近请求

题目重解:我们需要设计一个能统计最近3000毫秒内请求次数的系统。每当新的请求到来时,它会带有时间戳t,我们需要返回过去3000毫秒内(包括当前)发生的请求总数。这就像是在时间轴上维护一个滑动窗口,只...

力扣145:递归之美 轻松掌握二叉树后序遍历

力扣145:递归之美 轻松掌握二叉树后序遍历

题目解读二叉树的后序遍历是一种基础且重要的树遍历方式,其遍历顺序为:先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。这种遍历方式特别适合需要先处理子节点再处理父节点的场景,如内存释放...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。