最長遞增子序列

/*****************************************************************
 *description:最長遞增子序列
 *            給定數組arr,返回其最長遞增子序列。
 *            例:arr=[2,1,5,3,6,4,8,9,7] 返回[1,3,4,8,9]

 *****************************************************************/

#include<iostream>
#include<vector>
using namespace std;

//方法一:時間複雜度O(N^2)
//先創建一個和arr同樣大小的數組tmp,tmp[i]表示從0到i內最長遞增子序列長度
//則tmp[0]=1,tmp[i]等於max(tmp[j], 0<j<i且arr[j]<arr[i])
//得到tmp數組之後,遍歷tmp找到最長的子序列長度longest和其下標idx
//從idx開始,arr[idx]是答案的 最後一個元素,
//idx往前遍歷i,arr[i]<arr[idx]且tmp[i]==tmp[idx]-1,則i是倒數第二個,同理找到其它。
vector<int> longestSubSequence_1(const vector<int> arr)
{
    vector<int> res;
    if (arr.size() == 0)
        return res;

    vector<int> tmp(arr.size());
    tmp[0] = 1;
    for (int i = 1; i < arr.size(); i++)
    {
        int max = 0;
        for (int j = 0; j < i; j++)
        {
            if (arr[j] < arr[i])
            {
                max = max > tmp[j] ? max : tmp[j];
            }
        }
        tmp[i] = max + 1;
    }

    int endIdx = -1;
    int longest = 0;
    for (int i = 0; i < tmp.size(); i++)
    {
        if (tmp[i] > longest)
        {
            longest = tmp[i];
            endIdx = i;
        }
    }

    int last = endIdx;
    res.push_back(arr[endIdx]);
    for (int i = endIdx - 1; i >= 0; i--)
    {
        if (arr[i] < arr[last] && tmp[i] == tmp[last]-1)
        {
            res.push_back(arr[i]);
            last = i;
        }
    }
    reverse(res.begin(),res.end());
    return res;
}
//方法2:時間複雜度O(NlogN)
//利用二分法。
vector<int> longestSubSequence_2(const vector<int> arr)
{
    vector<int> res;
    if (arr.size() == 0)
        return res;

    vector<int> tmp(arr.size());
    vector<int> ends(arr.size());
    int right = 0;
    tmp[0] = 1;
    ends[0] = arr[0];

    int l = 0;
    int r = 0;
    int m = 0;

    for (int i = 1; i < arr.size(); i++)
    {
        l = 0;
        r = right;
        while (l <= r)
        {
            m = (l+r)/2;
            if (ends[m] < arr[i])
                l = m + 1;
            else
                r = m - 1;
        }
        right = right > l ? right : l;
        ends[l] = arr[i];
        tmp[i] = l + 1;
    }

    for (int i = 0; i < tmp.size(); i++)
        cout << tmp[i] << " ";
    cout << endl;

    int endIdx = -1;
    int longest = 0;
    for (int i = 0; i < tmp.size(); i++)
    {
        if (tmp[i] > longest)
        {
            longest = tmp[i];
            endIdx = i;
        }
    }

    int last = endIdx;
    res.push_back(arr[endIdx]);
    for (int i = endIdx - 1; i >= 0; i--)
    {
        if (arr[i] < arr[last] && tmp[i] == tmp[last]-1)
        {
            res.push_back(arr[i]);
            last = i;
        }
    }
    reverse(res.begin(),res.end());
    return res;

}

int main()
{
    vector<int> arr;
    arr.push_back(2);
    arr.push_back(1);
    arr.push_back(5);
    arr.push_back(3);
    arr.push_back(6);
    arr.push_back(4);
    arr.push_back(8);
    arr.push_back(9);
    arr.push_back(7);

    vector<int> res = longestSubSequence_2(arr);
    for (int i = 0; i < res.size(); i++)
        cout << res[i] << " ";

    return 0;
}


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