lis最长递增子序列

lis的实现有三种,一种是简单的O(n^2)的dp,第二种是转化为lcs,用原序列排序后得到一个有序的序列,并求两序列的最长公共子序列。这种可以比较方便地打印出答案,复杂度也是O(n^2)。最后是维护一个为某个长度时该长度序列的最后一个数可取的最小值,用了二分查找将复杂度降到O(nlogn)。

 1 //LIS
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <list>
 5 #include <vector>
 6 
 7 using namespace std;
 8 
 9 int dp[105];
10 
11 void lis(int *p, int n) {
12     memset(dp, 0, sizeof(dp));
13 
14     for (int i = 1;i < n;i++) {
15         dp[i] = dp[i - 1];
16         for (int j = 0;j < i;j++)
17             if (p[i] > p[j])dp[i] = max(dp[i], dp[j] + 1);
18     }
19     cout << dp[n - 1];
20 }
21 
22 int d[105][105];
23 void lcs(int*p, int* q, int m, int n) {//m,n为两个数组的长度
24 
25     memset(d, 0, sizeof(d));
26 
27     for (int i = 1;i<m + 1;i++)
28         for (int j = 1;j < n + 1;j++) {
29             if (p[i - 1] == q[j - 1])d[i][j] = d[i - 1][j - 1] + 1;
30             else d[i][j] = max(d[i - 1][j], d[i][j - 1]);
31         }
32 }
33 
34 void print_ans(int* p, int* q, int m, int n) {//lcs的打印
35     if (d[m][n] <= 0)return;
36 
37     if (d[m][n] == d[m - 1][n - 1] + 1) {
38         print_ans(p, q, m - 1, n - 1);
39         cout << p[m - 1];
40     }
41     else if (d[m][n] = d[m - 1][n])
42         print_ans(p, q, m - 1, n);
43     else
44         print_ans(p, q, m, n - 1);
45     //cout << endl;
46 }
47 
48 int binarysearch(int* a, int len, int val) {
49     int left = 0, right = len;//左闭右开
50     while (left < right) {
51         int mid = (left + right) / 2;
52         if (a[mid] > val)
53             right = mid;
54         else if (a[mid] < val)
55             left = mid + 1;
56         else
57             return mid;
58     }
59     return left;
60 }
61 
62 int lis1(int *p, int n) {
63     int *a = new int[n];
64     int length = 1;
65     a[0] = p[0];
66 
67     for (int i = 1;i < n;i++) {
68         if (p[i] > a[length - 1])
69             a[length++] = p[i];
70         else
71             a[binarysearch(a, length, p[i])] = p[i];
72     }
73 
74     delete a;
75     return length;
76 }

 

转载于:https://www.cnblogs.com/schsb/p/8686300.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值