300.最长递增子序列

300.最长递增子序列

过程示例-bilibili                    思路讲解 csdn

题目:

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

最长严格递增子序列的意思,删除影响nums数组内的元素从小到大排列的其他元素,留下一个从小到大排列的最大数组 

思路:

求最长递增子序列,那就设dp[i]是以 i 结尾的 最长严格递增子序列

dp[i]怎么推出的递推公式呢?不知道

用这个例子推导一下,用nums[2,3,7,101]

可以推出

nums = [10,9,2,5,3...

    dp =  [1,1,1,2,2...

依靠定义直接观察可以发现,nums[0]=10对应dp[0]=1,说明这个时候的子序列最长为1

然后的nums[1]=9,nums[2]=2,对应的因为都比前面的10小就都让dp为1

到了nums[3]=5,发现前面有个2比他小,然后+1变成了2,num[4]=3,同理。

感觉出某种模糊的规律了。最小的dp数组都初始化为1,然后比较一下之前的num[i]的值,又没有比当前遍历的dp[i] 对应的num[i]的值小的,有的话就在他的基础上+1。

因为求的是最大长度,所以多了一个最大值,最长子序列长度+1。

抽象为代码:

for (int i = 0; i < nums.length; i++) {
    for (int j = 0; j < i; j++) {
        // 寻找 nums[0..j-1] 中比 nums[i] 小的元素
        if (nums[i] > nums[j]) {
            // 把 nums[i] 接在后面,即可形成长度为 dp[j] + 1,
            // 且以 nums[i] 为结尾的递增子序列
            dp[i] = Math.max(dp[i], dp[j] + 1);
        }
    }
}

然后返回里面遍历后dp[i]的最大值就是所求最大长度了

总代码

class Solution {
public:
    int lengthOfLIS(vector& nums) {
        if (nums.size() <= 1) return nums.size();
        vector dp(nums.size(), 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[i], dp[j] + 1);
            }
            if (dp[i] > result) result = dp[i]; // 取长的子序列
        }
        return result;
    }
};

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