代码随想录训练营第52天|300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组

300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组

300.最长递增子序列

对于该题,我们应该用回溯算法进行求解。
我们可以用dp数组来进行动态规划,用dp[ii]来记录以nums[ii]结尾的最长递增子序列,因此,最后我们返回dp数组的最大值即可。
动态规划四部曲。
1.dp数组的含义为以nums[ii]结尾的最长递增子序列长度。
2.dp数组的推导公式。
我们定义一个临时变量用于遍历并记录以nums[ii]结尾的可能最长子序列长度,如果当前数字nums[ii]大于遍历的nums[jj],此时就可以将nums[ii]加到nums[jj]后面,形成更长的子序列长度,因此,如果temp比dp[jj]+1(dp[jj]表示截止到nums[jj]最长的子序列长度)小的话,我们就令temp更新为dp[jj]+1。

			int temp = 1;
            for(int jj = 0;jj<ii;jj++)
            {
                if(nums[ii]>nums[jj]) temp = max(dp[jj]+1,temp);
            }
            dp[ii] = temp;

3.dp数组的初始化,初始情况,任何一个数字都可以构成一个子序列,因此,我们令dp数组的所有元素都为1。
4.遍历顺序,从前向后进行遍历。

代码

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int len = nums.size();
        vector<int> dp(len,1);
        for(int ii =1;ii<len;ii++)
        {
            int temp = 1;
            for(int jj = 0;jj<ii;jj++)
            {
                if(nums[ii]>nums[jj]) temp = max(dp[jj]+1,temp);
            }
            dp[ii] = temp;
        }
        int result = dp[0];
        for(int ii =1;ii<len;ii++)
            result = max(result,dp[ii]);
         return result;
    }
};

674.最长连续递增序列

双指针

首先,我们可以利用双指针的思想,利用快慢指针,我们定义一个结果量result,一个临时量temp,快指针遍历一次数组,如果快指针大于快指针前一个元素,就让temp++,如果此时temp大于了result,就跟新result。如果快指针小于等于前一个元素,我们就让慢指针low指向fast所指位置。
最后返回result即可。

代码

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int result = 1;
        if(nums.size()==1) return 1;
        int low = 0,fast = 1;
        for(;fast<nums.size();fast++)
            if(nums[fast]>nums[fast-1]) 
                result = max(result,fast-low+1);
            else
                low=fast;
        return result;
    }
};

动态规划

我们用dp数组来记录当前最长子序列长度,如果当前遍历的数字比前一个大,则我们更新dp[ii]让其等于dp[ii-1]+1,表示该元素可以增长这个连续递增序列。
动态规划四部曲。
1.dp数组的含义,包含当前元素的最长子序列长度。
2.dp数组的推导公式,if(nums[ii]>nums[ii-1])dp[ii] = dp[ii-1]+1;
3.dp数组的初始化,我们令dp数组最初都为1,这样访问时,即使连续子序列断掉,我们也可以继续访问。
4.遍历顺序,从前往后进行遍历。

代码

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        vector<int>dp(nums.size(),1);
        int result = 1;
        for(int ii =1;ii<nums.size();ii++)
        {
            if(nums[ii]>nums[ii-1])dp[ii] = dp[ii-1]+1;
            result = max(result,dp[ii]);
        }
        return result;
    }
};

718.最长重复子数组

我们可以用动态规划的思路。
我们用dp数组来解决。dp[ii][jj]表示以nums2[ii-1]、nums1[jj-1]结尾的最长重复子数组。如果nums2[ii-1]=nums1[jj-1],那么我们让dp[ii][jj]进行更新,因为其含义,所以更新的话,需要dp[ii-1][jj-1],即在dp[ii-1][jj-1]的基础上进行+1;
对此,动态规划四部曲。
1.dp数组含义,dp数组用于记录以nums2[ii-1]、nums1[jj-1]结尾的最长重复子数组的长度。
2.dp数组的推导公式。

if(nums2[ii-1]==nums1[jj-1]) 
{
      dp[ii][jj] = dp[ii-1][jj-1]+1;
                            
}

3.dp数组的初始化。我们令dp数组初始全为零,表示遍历之前没有相同的元素。
4.遍历顺序。我们用两层for循环,分别循环两个数组,表示两个数组每个元素都进行一次比较。

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
            vector<vector<int>>dp(nums2.size()+1,vector<int>(nums1.size()+1,0));
            int result = 0;
            for(int ii =1;ii<nums2.size()+1;ii++)
            {
                for(int jj =1;jj<nums1.size()+1;jj++)
                    if(nums2[ii-1]==nums1[jj-1]) 
                        {
                            dp[ii][jj] = dp[ii-1][jj-1]+1;
                            result=max(result,dp[ii][jj]);
                        }
            }
            return result;
    }
};

你可能感兴趣的:(算法,动态规划,leetcode)