Leetcode 300: 最长递增子序列

Leetcode 300: 最长递增子序列

问题描述:

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

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

算法原理

本问题的关键是要维护这样一个数组q[1~k]:其中q[i]表示最长递增子序列长度为i的最小的结尾值。因此,可通过反证法,知数组q里面的元素是严格单调递增的。遍历到nums[i]后,我们要找到q中最后一个小于nums[i]的元素(假设下标为r),则q中下标为r + 1的元素就应该更新为nums[i]。当我们遍历完数组nums后, q数组的长度就是我们要求的答案。(q的长度就是 曾经出现过的最长递增子序列的长度)

Note: 需要以下几种特殊情况:

  • q为空
  • q的第一个元素大于 nums[i]
  • nums[i] 大于 q中的最后一个元素

Leetcode代码

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> q;
        for (int i = 0; i < nums.size(); i ++ ) {
            if (q.empty()) {
                q.push_back(nums[i]);
            } else {
                if (nums[i] <= q[0]) q[0] = nums[i]; //注意等号
                else if (nums[i] > q.back()) q.push_back(nums[i]);
                else {
                    int l = 0, r = q.size() - 1;
                    while (l < r) {
                        int mid = (l + r + 1) >> 1;
                        if (q[mid] < nums[i]) l = mid; //找到 < nums[i] 的最后一个数,不是 <= !
                        else r = mid - 1;
                    }
                    q[r + 1] = nums[i];
                }
            }
        }
        return q.size();
    }
};

你可能感兴趣的:(leetcode,leetcode,算法)