300. Longest Increasing Subsequence**

300. Longest Increasing Subsequence**

https://leetcode.com/problems/longest-increasing-subsequence/

題目描述

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4 
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. 

Note:

  • There may be more than one LIS combination, it is only necessary for you to return the length.
  • Your algorithm should run in O(n2)O(n^2) complexity.

Follow up: Could you improve it to O(nlogn)O(n log n) time complexity?

C++ 實現 1

動態規劃.

使用 f[i] 表示以 nums[i] 結尾的 LIS. 那麼:

f[i] = max(nums[i] > nums[k] ? (f[k] + 1) : 1, f[i]); 其中 k = 1, 2, ..., i - 1

上面意思就是說, nums[i] 要和它之前的所有數字 nums[k] 進行比較, 從而找到 LIS.

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if (nums.empty()) return 0;
        int res = 1;
        vector<int> f(nums.size(), 1);
        for (int i = 1; i < nums.size(); ++ i) {
            for (int j = i - 1; j >= 0; -- j) {
                auto tmp = nums[i] > nums[j] ? f[j] + 1 : 1;
                f[i] = std::max(f[i], tmp);
            }
            res = std::max(f[i], res);
        }
        return res;
    }
};

C++ 實現 2

思路和 C++ 實現 1 一致, 寫法稍不同.

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if (nums.empty()) return 0;
        int n = nums.size();
        vector<int> dp(n, 1);
        for (int i = 1; i < n; ++i) {
            for (int k = i - 1; k >= 0; k--)
                if (nums[k] < nums[i])
                    dp[i] = (dp[k] + 1) > dp[i] ? (dp[k] + 1) : dp[i];
        }
        return *max_element(dp.begin(), dp.end());
    }
};

C++ 實現 3

Follow Up 中要求的 O(NlogN)O(N \log N) 方法. 相當於是將 LIS 給找出來了, 使用 res 存儲 LIS, 對於放在 LIS 中的每個元素, 如果我們訪問到 nums[i] 時, 發現 res 中有比 nums[i] 更大(或等於) 的元素, 就替換該元素. 這裏不用 upper_bound, 否則最後出來的 LIS 就會有重複元素, 不符合 LIS 的定義.

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if (nums.empty()) return 0;
        vector<int> res;
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            if (res.empty() || nums[i] > res.back())
                res.push_back(nums[i]);
            else if (nums[i] < res.back()) {
                // lower_bound 是 res 中第一個大於或等於 nums[i] 的元素
                auto iter = std::lower_bound(res.begin(), res.end(), nums[i]);
                *iter = nums[i];
            }
        }
        return res.size();
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章