从动态规划到贪心算法:最长递增子序列问题的方法全解析
创始人
2024-11-23 18:37:00
0

主页:17_Kevin-CSDN博客

专栏:《算法》


目录

题型简介

题解代码

解题思路

剔骨刀(精细点)


题型简介

经典例题:300. 最长递增子序列 - 力扣(LeetCode)

最长递增子序列(Longest Increasing subsequence,LIS)是一个经典的问题。最长递增子序列是指在一个序列中,以不下降的顺序连续排列的一系列元素的子序列。这个子序列的长度就是最长递增子序列的长度。

题解代码

虽然注释详细,但与后文解题思路对应食用风味更佳~

#include  #include   using namespace std;  int lengthOfLIS(vector& nums)  {     // 如果输入序列为空,返回 0     if (nums.empty())      {         return 0;     }      // 定义 dp 数组,长度为输入序列的长度     int dp[nums.size()];     // 初始化 dp 数组,将所有元素初始化为 1     for (int i = 0; i < nums.size(); i++)      {         dp[i] = 1;     }      // 记录最长递增子序列的长度     int maxn = 1;      // 遍历输入序列,从第 2 个元素开始,因为第一个元素的 dp[0] 一定是 1     for (int i = 1; i < nums.size(); i++)      {         // 遍历之前的元素,找到满足条件的索引 j         for (int j = 0; j < i; j++)          {             // 如果当前元素小于之前的元素,并且之前元素的最长递增子序列长度加 1 大于当前元素的最长递增子序列长度             if ((nums[j] < nums[i]) && (dp[j] + 1 > dp[i]))              {                 // 更新当前元素的最长递增子序列长度为之前元素的最长递增子序列长度加 1                 // 因为if条件是nums[j] < nums[i],所以当前i位置的num一定是可以往j位置的数字后拼接作为递增子序列的                 // 所以更新当前i的dp作为新的当前dp[i]                 dp[i] = dp[j] + 1;             }         }          // 在与每次遍历完当前i的j后更新的dp[i]与之前的maxn作对比         // 得到当前最长递增子序列的长度         if (dp[i] > maxn)          {             maxn = dp[i];         }     }      // 返回最长递增子序列的长度     return maxn; }  int main()  {     vector nums = { 10, 9, 2, 5, 3, 7, 101, 18 };     // 输出:4     cout << lengthOfLIS(nums) << endl;      return 0; }

解题思路

1. 贪心策略(Greedy algorithms):

贪心算法的核心是以少博多,以最优解为目标

贪心策略是选择当前未处理元素中最小的元素,将其添加到最长递增子序列的末尾。这种策略的基本思想是尽可能地选择较小的元素,以保证子序列的递增性。

在代码中,我们通过比较当前元素 nums[i] 和之前元素 nums[j]j < i)的大小来更新最长递增子序列的长度。如果 nums[j] < nums[i],并且 dp[j] + 1 > dp[i],我们就选择 nums[j] 作为最长递增子序列的一部分,并更新 dp[i] 为 dp[j] + 1

2. 动态规划(Dynamic programming):

动态规划是一种通过将问题分解为子问题来解决问题的方法。在最长递增子序列问题中,动态规划的基本思想是通过递推公式来计算每个元素的最长递增子序列长度。

在代码中,我们使用了一个长度为 nums.size() 的数组 dp 来存储每个元素的最长递增子序列长度。递推公式为 dp[i] = max(dp[j] + 1, dp[i]),其中 j < i 表示之前的元素。通过递推公式,我们可以逐步计算出每个元素的最长递增子序列长度。

剔骨刀(精细点)

    for (int i = 1; i < nums.size(); i++)      {         for (int j = 0; j < i; j++)          {             if ((nums[j] < nums[i]) && (dp[j] + 1 > dp[i]))              {                 dp[i] = dp[j] + 1;             }         }          if (dp[i] > maxn)          {             maxn = dp[i];         }     }

动态规划问题难点在于它的递推公式理解。

这里的 (nums[j] < nums[i]) && (dp[j] + 1 > dp[i]) 中的 dp[j] 可以当做前面已经在该下标上取得的最长递增子序列的个数,因为if条件(nums[j] < nums[i]) && (dp[j] + 1 > dp[i]),当条件通过时说明当前 i 位置的num一定是可以往j位置的数字后拼接作为递增子序列的,所以dp[j] + 1的意思就是说,只要在if条件内他都可以拼接,但是如果dp[j] + 1都小于dp[i]的话,那么它就不是最长子序列了,不会进行 +1 ,保留原来的 dp[i] 大小。  


相关内容

热门资讯

透视安卓版!wepoker有辅... 透视安卓版!wepoker有辅助插件吗,wepoker辅助器下载(果然有挂);wepoker有辅助插...
透视辅助!wpk透视辅助方法,... 透视辅助!wpk透视辅助方法,wpk俱乐部有没有辅助,攻略教程(原来是真的有挂)1、下载好wpk俱乐...
透视真的!aapoker透视脚... 透视真的!aapoker透视脚本入口,aapoker俱乐部靠谱吗,扑克教程(有挂黑科技)1、进入到a...
透视教程!wepoker辅助器... 透视教程!wepoker辅助器,wepoker亲友圈有用吗(确实存在有挂);1、wepoker亲友圈...
透视最新!wpk透视是真的吗,... 透视最新!wpk透视是真的吗,wpk软件是正规的吗,科技教程(总是存在有挂)1、每一步都需要思考,不...
透视攻略!aapoker怎么提... 透视攻略!aapoker怎么提高中牌率,aapoker免费透视脚本,扑克教程(有挂黑科技)1、下载好...
透视肯定!wejoker辅助器... 透视肯定!wejoker辅助器怎么卖,wepoker怎么挂飞机(总是有挂)1、wejoker辅助器怎...
透视能赢!wpk俱乐部是做什么... 透视能赢!wpk俱乐部是做什么的,wpk透视辅助方法,曝光教程(好像是有挂);1、操作简单,无需注册...
透视线上!wpk控制牌是真的吗... 透视线上!wpk控制牌是真的吗,wpk俱乐部是真的吗,德州论坛(总是真的有挂)1、在wpk控制牌是真...
透视软件!wepoker辅助是... 透视软件!wepoker辅助是真的假的,wepokerplus万能挂(一贯有挂)1)wepoker辅...