代码随想录训练营:1.最长上升子序列、2.最长连续递增序列、3.最长重复子序列、4.最长公共子序列

1.最长上升子序列:代码随想录

代码随想录训练营:1.最长上升子序列、2.最长连续递增序列、3.最长重复子序列、4.最长公共子序列_第1张图片

 

        1.本来的疑问:为何要if(nums[i] > nums[j])才有后面的递推公式?可以自己举个栗子:

当nums=[4.3.2.5.6.7]的时候,若i= 2,那么j=(0,1)的时候,无法与nums[2]构成递增序列,不符合if()判断语句,就跳过。

        2.每一个针对于i的for循环,都只更新一个i(大循环),大循环中的最后if语句就是为了取最后dp数组中的最大值。

        3.本题最重要的就是递推公式,想到dp[i]是怎么推出的,是由他前面的一些状态推出的,并取最大值。

        4.在写代码的时候不要把第二个for循环中的nums[i]、nums[j]错写成dp[i],dp[j],注意。

2.最长连续递增序列:代码随想录

代码随想录训练营:1.最长上升子序列、2.最长连续递增序列、3.最长重复子序列、4.最长公共子序列_第2张图片

 

        1.为什么for循环中i

        2.此题和上一题的区别在于遍历顺序和递推公式,引用卡哥的话,不连续的子序列和前0~i个状态都有关,而连续的子序列只和前一个状态有关。

3.最长重复子数组:代码随想录

代码随想录训练营:1.最长上升子序列、2.最长连续递增序列、3.最长重复子序列、4.最长公共子序列_第3张图片

 

        1.疑问:为什么“即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;”这句话怎么理解,因为我也不一定是在子串的最后一个字母比较啊。解答:可以按照卡哥画的那个图对照着进行理解,因为是嵌套for循环,相当于是先把数组A里面的某个数固定住了,然后遍历数组B里面的每个数,拿数组B里面的数一个个的和这个固定的A数组里面的数去比,如果两者相等的话,dp[i][j]就去看看,数组A的上一个数和数组B的上一个数是否相等(其状态就是dp[i-1][j-1])然后在dp[i-1][j-1]的基础上加一。

        2.写代码的时候注意,第二个if()判断语句是在第二个for循环中,不是在第一个for循环里面。

4.最长公共子序列:代码随想录

代码随想录训练营:1.最长上升子序列、2.最长连续递增序列、3.最长重复子序列、4.最长公共子序列_第4张图片

 

        1.本题和上一题的区别就是,上一题中重复序列必须是相邻的才行,而本题中公共序列不需要是相邻的,所以与上题中的递推公式就会有一定的区别。

        2.刚才理解了半天递推公式的意思,终于弄清楚了。主要还是要把dp[i][j]的意思给牢记在心。

如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;这句话的意思就是和上一题一样,找到两个相同的元素,就会根据上一个状态+1.

如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。

重点是这一句话,因为公共序列不需要相邻的,那么我们就可以从两个方向来推导他。取这两个方向中的最大值,而不是像上一题中,若二者不相等的话,dp[i][j]还是保持原值不变。

        3.并且由于dp[i][j]是从两个方向推导过来的取最大值,所以是越往后越大,故最后return的是二维dp数组中的最后一个值,而不像上一题中return的是max()。

你可能感兴趣的:(算法,数据结构,leetcode)