*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;
}