ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

微软面试题: LeetCode 300. 最长递增子序列 出现次数:2

2021-04-10 21:04:26  阅读:111  来源: 互联网

标签:面试题 nums 300 int tail 数组 序列 LeetCode dp


题目描述:

 

 解析:

参考 VV大神 的题解:

https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/dong-tai-gui-hua-er-fen-cha-zhao-tan-xin-suan-fa-p/

方法一: 动态规划    

//dp time: O(n^2)   memory :O(n) 1. 定义状态:

  基于「动态规划」的状态设计需要满足「无后效性」的设计思想,可以将状态定义为「以 nums[i] 结尾 的「上升子序列」的长度」。

「无后效性」的设计思想:让不确定的因素确定下来,以保证求解的过程形成一个逻辑上的有向无环图。这题不确定的因素是某个元素是否被选中,

而我们设计状态的时候,让 nums[i] 必需被选中,这一点是「让不确定的因素确定下来」,也是我们这样设计状态的原因。

  2. 状态转移方程:

       如果一个较大的数接在较小的数后面,就会形成一个更长的子序列。只要 nums[i] 严格大于在它位置之前的某个数,那么 nums[i] 就可以接在

这个数后面形成一个更长的上升子序列。

 

3. 初始化:

dp[i] = 1,11 个字符显然是长度为 11 的上升子序列。

 

4. 输出:

状态数组 dp 的最大值。

 

5  空间优化:

遍历到一个新数的时候,之前所有的状态值都得保留,因此无法优化空间。

代码:

 1 //dp time: O(n^2)   memory :O(n)
 2     int lengthOfLIS(vector<int>& nums)
 3     {
 4         int res = 1;
 5         vector<int> dp(nums.size(),1);
 6         for(int i = 1; i < nums.size(); ++i)
 7         {
 8             for(int j = 0; j < i ;++j)
 9             {
10                 if(nums[j] < nums[i])
11                 {
12                     dp[i] = max(dp[i],dp[j] + 1);
13                 }
14             }
15             res = max(res,dp[i]);
16         }
17         return res;
18     }

 

方法二:dp  修改状态定义(同时用到了贪心算法、二分查找)

  状态设计思想:依然着眼于某个上升子序列的结尾的元素,如果已经得到的上升子序列的结尾的数越小,那么遍历的时候后面接上一个数,

会有更大的可能构成一个长度更长的上升子序列。既然结尾越小越好,我们可以记录 在长度固定的情况下,结尾最小的那个元素的数值,这样定义

以后容易得到「状态转移方程」。

     1 .定义新状态(特别重要)

tail[i] 表示:长度为 i + 1 的 所有 上升子序列的结尾的最小值。

     数组 tail 也是一个严格上升数组。

    2. 状态初始化

  遍历第 1 个数 nums[0],直接放在有序数组 tail 的开头 tail[0] = nums[0]

    3.状态转移

3.1  在遍历数组 nums 的过程中,看到一个新数 num,如果这个数 严格 大于有序数组 tail 的最后一个元素,就把 num 放在有序数组 tail 的后面,否则进入第 2 点;

3.2  在有序数组 tail 中查找第 1 个等于大于 num 的那个数,用新数 num 替换;

   4. 输出:

有序数组 tail 的长度,就是所求的「最长上升子序列」的长度。

   5. 空间优化:

无法优化空间。

 1 //dp time: O(n*logn)   memory :O(n)
 2     int lengthOfLIS(vector<int>& nums)
 3     {
 4         //tail[i]:当前长度为 i+1 的递增子序列中,结尾元素最小的递增子序列的结尾元素值
 5         vector<int> tail;
 6         tail.push_back(nums[0]);
 7         for(int i = 1; i < nums.size(); ++i)
 8         {
 9             if(nums[i] > tail.back())
10             {
11                 tail.push_back(nums[i]);
12             }
13             else
14             {
15                 int j = std::lower_bound(tail.begin(),tail.end(),nums[i]) - tail.begin();
16                 tail[j] = nums[i];
17             }  
18         }
19         return tail.size();
20     }

 

标签:面试题,nums,300,int,tail,数组,序列,LeetCode,dp
来源: https://www.cnblogs.com/wangxf2019/p/14642082.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有