目录
- 1.最长递增子序列的个数
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
- 2.最长数对链
- 1.题目链接
- 2.算法原理详解
- 3.代码实现
1.最长递增子序列的个数
1.题目链接
- 最长递增子序列的个数
2.算法原理详解
- 注意:本题思路和思维方式及用到的方法很值得考究,个人感觉很有含金量,且初见不好理解
- 前置知识:如何在数组中一次遍历就找出最大值出现的次数?
x == maxVal
:count++
x < maxVal
:无视x > maxVal
:更新最大值,重新计数int maxVal = nums[0], count = 1; for(int i = 1; i < nums.size(); i++) {if(nums[i] == maxVal){count++;}else if(nums[i] > maxVal){maxVal = nums[i];count = 1;} }
- 思路:
-
确定状态表示 ->
dp[i]
的含义- 以
i
位置元素为结尾的所有子序列中,最长递增子序列的个数 - 本题状态标识还可以继续划分
len[i]
:以i
位置元素为结尾的所有子序列中,最长递增子序列的"长度"count[i]
:以i
位置元素为结尾的所有子序列中,最长递增子序列的"个数"
- 以
-
推导状态转移方程
- 令
j
为i
前面的任一一个数
- 令
-
初始化:
vector<int> len(n, 1), count(n, 1)
-
确定填表顺序:从左往右,两个表一起填
-
确定返回值:前置知识部分用到的小贪心策略,见代码
-
3.代码实现
int findNumberOfLIS(vector<int>& nums)
{int n = nums.size();vector<int> len(n, 1), count(n, 1);int retLen = 1, retCount = 1;for(int i = 1; i < n; i++){for(int j = 0; j < i; j++){if(nums[j] < nums[i]){if(len[j] + 1 == len[i]){count[i] += count[j];}else if(len[j] + 1 > len[i]){len[i] = len[j] + 1;count[i] = count[j];}}}if(retLen == len[i]){retCount += count[i];}else if(retLen < len[i]){retLen = len[i];retCount = count[i];}}return retCount;
}
2.最长数对链
1.题目链接
- 最长数对链
2.算法原理详解
- 预处理:按照第一个元素排序
- 此时问题就转化成了最长递增子序列了
- 目的:保证当前位置不存在可以连在它后面的数对的后面的可能
- 思路:
-
确定状态表示 ->
dp[i]
的含义- 以
i
位置元素为结尾的所有子序列中,最长的数对链长度
- 以
-
推导状态转移方程
-
初始化:
vector<int> dp(n, 1)
-
确定填表顺序:从左往右
-
确定返回值:整个
dp
表里的最大值
-
3.代码实现
int findLongestChain(vector<vector<int>>& pairs)
{sort(pairs.begin(), pairs.end()); // 预处理int n = pairs.size();vector<int> dp(n, 1);int ret = 1;for(int i = 1; i < n; i++){for(int j = 0; j < i; j++){if(pairs[j][1] < pairs[i][0]){dp[i] = max(dp[j] + 1, dp[i]);}}ret = max(ret, dp[i]);}return ret;
}