版权声明:本文为博主原创文章,可以转载但必须注明出处。 https://blog.csdn.net/nirendao/article/details/81263414
最长上升/下降子序列
给定一个数组,求其中最长的上升子序列的长度(求最长下降子序列也是一样的算法)。这个问题还可以这么问:求最长上升子序列是什么。
这是一个动态规划的问题。以第i个节点处为最后一个节点的最长上升序列是什么呢?自然是要查看之前 i-1 个节点最长上升序列的长度。如果以节点 x (1<=x<=i-1) 为最终节点的最长上升子序列为 n ,并且 x 节点的值小于 i 节点的值,那么以 i 节点为最终节点的最长上升序列就可以是 n+1 长度了。如此,只要知道 1 到 i-1 节点的情况,就能知道以 i 为最终节点的最长上升子序列的长度。这就相当于状态转移方程了。而第1个节点的最长上升序列就是1.
这个是O(n^2)的算法复杂度。实际上还可以做到O(nlogn)的复杂度,本文没有继续进一步挖掘了。
写成程序也不难,如下:
int array[] = {10, 34, 56, 32, 45, 66, 88, 43, 99};
int size = sizeof(array)/sizeof(int);
vector<int> records(size, 1); // 记录以每个节点为最终节点时的最长上升子序列的长度,全部初始化为1,因为序列中只有自己一个节点时就是1
for (int i=0; i<size; ++i) {
for (int j=0; j<i; ++j) {
if (array[j] < array[i]) {
if (records[j]+1 > records[i]) {
records[i] = records[j] + 1;
}
}
}
}
以上的程序可以计算出最长上升子序列的长度了,但具体最长上升子序列是什么呢?其实依据上述的程序,也很好计算了。比如,给每个节点对应一个链表,记录以该节点为最终节点时的最长上升序列。最后一个节点的链表,就是最长上升子序列了。当然,最长上升子序列可能并不是唯一的,这里只去找到其中一个即可。
完整代码如下:(记录最长上升子序列的链表的代码可能并不是最优的,只是代码可读性上较好)
#include <iostream>
#include <vector>
using namespace std;
void print_vector(vector<int>& vec)
{
for (auto i : vec){
cout << i << ", ";
}
cout << endl;
}
struct Node {
int data;
Node *next;
Node(int d):data(d){next = NULL;}
};
Node* clone_list(Node *head)
{
if (head == NULL) return NULL;
Node *p = NULL;
Node *h = NULL;
bool first = true;
while(head != NULL) {
Node *tmp = new Node(head->data);
if (first == true) {
h = tmp;
p = tmp;
first = false;
}
else {
p->next = tmp;
p = p->next;
p->next = NULL;
}
head = head->next;
}
return h;
}
void delete_list(Node *head)
{
if (head == NULL) return;
while (head != NULL) {
Node *tmp = head;
head = head->next;
delete tmp;
}
}
Node * add_one_node(Node *head, int data)
{
Node *tmp = new Node(data);
if (head == NULL) return tmp;
Node *hh = head;
while(head->next != NULL) head = head->next;
head->next = tmp;
return hh;
}
void print_list(Node *head)
{
while(head != NULL) {
cout << head->data << ", ";
head = head->next;
}
cout << endl;
}
int main()
{
int array[] = {10, 34, 56, 32, 45, 66, 88, 43, 99};
int size = sizeof(array)/sizeof(int);
vector<int> records(size, 1);
vector<Node *> lists(size, NULL);
Node *a0 = new Node(array[0]);
lists[0] = a0;
for (int i=0; i<size; ++i) {
for (int j=0; j<i; ++j) {
if (array[j] < array[i]) {
if (records[j]+1 > records[i]) {
records[i] = records[j] + 1;
delete_list(lists[i]);
lists[i] = clone_list(lists[j]);
add_one_node(lists[i], array[i]);
}
}
}
}
print_vector(records);
for (int i=0; i<size; i++)
print_list(lists[i]);
return 0;
}
(完)