题1:
指路:300. 最长递增子序列 - 力扣(LeetCode)
思路与代码:
求最长递增子序列,那么就定义一个数组dp[i],含义为最长递增子序列。这里有一个小问题,这里的序列的范围为何。如果把遍历范围定为全数组那和暴力无异,显然也不符合O(nlogn)的要求。那么在这里我们定义遍历范围的时候就要把dp[i]定义为以nums[i]结尾的最长递增子序列的长度。随后我们定义一个j在i的范围内遍历,当nums[i]>nums[j]时,在这里就得到了一个dp[i]=dp[j]+1,而我们要求的是最大递增子序列,那么要在原有的dp[i]和得到的dp[i]中取较大值,也就是dp[i]=max(dp[i], dp[j] + 1)。最后我们看需要输出的是什么,在样例中我们可以看到绝对不再是dp[nums.size()-1],我们需要的是整个数组的最长递增子序列,那么就需要遍历整个数组的dp值,取出最大的即可。代码如下:
class Solution {
public:int lengthOfLIS(vector<int>& nums) {// dp数组的含义为最长递增子序列长度if (nums.size() <= 1) return nums.size();vector<int> dp(nums.size(), 1);dp[0] = 1;int result = 0;// 递推for (int i = 1; i < nums.size(); i++) {for (int j = 0; j < i; j++) {if (nums[i] > nums[j]) {dp[i] = max(dp[j] + 1, dp[i]);}if (dp[i] > result) result = dp[i];}}return result ;}
};
题2:
指路:674. 最长连续递增序列 - 力扣(LeetCode)
思路与代码:
1.动态规划
区别于上题者为“连续”。连续就很方便了,比较清楚相邻的两个就好了,也就是nums[i]与nums[i-1]是否相等。注意这里的子序列,即使最短也是1,因此,result初始为1。代码如下:
class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {if (nums.size() == 0) return 0;vector<int> dp(nums.size(), 1);int result = 1;dp[0] = 1;for (int i = 1; i < nums.size(); i++) {if (nums[i] > nums[i - 1]) { dp[i] = dp[i - 1] + 1;}if (dp[i] > result) result = dp[i];}return result;}
};
2.贪心
class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {if (nums.size() == 0) return 0;int result = 1;int count = 1;for (int i = 1; i < nums.size(); i++) {if (nums[i] > nums[i - 1]) {count++;}else {count = 1;}if (count > result) result = count;}return result;}
};
题3:
指路:718. 最长重复子数组 - 力扣(LeetCode)
思路与代码:
两个数组,那么不妨定义一个二维数组记录两个数组的比较情况,dp[i][j]的含义为以下标i-1为尾和j-1为尾的最长重复子数组的长度为dp[i][j]。将尾划定为i-1和j-1而非i和j的原因是,在初始化数组时如果尾为i,j,那么我们需要对数组进行两行的初始化:
for (int i = 0; i < nums1.size(); i++) if (nums1[i] == nums2[0]) dp[i][0] = 1;for (int j = 0; j < nums2.size(); j++) if (nums1[0] == nums2[j]) dp[0][j] = 1;
而如果将尾划为i-1和j-1时,初始化直接定义为0即可。我们读题可以知道dp[i][j]的状态得于前面的状态,即dp[i][j]=dp[i-1][j-1] + 1,因为在比较两个数组中元素后,两个数组中的元素都需要后退一个从而达到比较全者的要求。在这里遍历顺序无谓先后,选择最普通的一种,外层数组1,内层数组2。注意,因为前面将界限划定为i-1,所以这里要想遍历完数组1,那么i的取值范围就是小于等于nums1.size(),同理,j的遍历范围也一样。代码如下:
class Solution {
public:int findLength(vector<int>& nums1, vector<int>& nums2) {vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));int result = 0;for (int i = 1; i <= nums1.size(); i++) {for (int j = 1; j <= nums2.size(); j++) {if (nums1[i - 1] == nums2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;}if (dp[i][j] > result) result = dp[i][j];}}return result;}
};