问题:
在一个数组中寻找最长递增子序列。
动态规划方法:
当一个数要加入进来的时候有两种方法:
1、前面的数都比当前的数大(或者相等),因此,以这个数为止的最长递增子序列长度就是1。数组中的第一个数一般预先填好,或者设置哨兵。
2、前面的数有比当前的数小的,那么以这个数为止的最长递增子序列长度就是states[i] = max(states[i], states[j] + 1);所以对于每一个states[i]要
遍历它前面的states数组,并且对于每一个num[i] 要比较它前面的num数组来作为控制条件。
代码:
1 #include <iostream> 2 #include <algorithm> 3 4 int main() 5 { 6 #define LEN 7 7 int num[ LEN ] = {2, 9, 3, 6, 5, 1, 7}; 8 9 int states[LEN] = {0}; 10 11 states[0] = 1; 12 13 int max_subsequence = 1; 14 for(int i = 1; i < LEN; i++) 15 { 16 for(int j = 0; j < i; j++) 17 { 18 if(num[i] > num[j]) 19 { 20 states[i] = std::max(states[i], states[j] + 1); 21 } 22 } 23 max_subsequence = std::max(max_subsequence, states[i]); 24 } 25 26 27 std::cout << "max_subsequence : " << max_subsequence << std::endl; 28 29 return 0; 30 }
运行结果:
把最长子序列之一打印出来,需要借助一个pre数组,代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <stack> 4 int main() 5 { 6 #define LEN 7 7 int num[ LEN ] = {2, 9, 3, 6, 5, 1, 7}; 8 int pre[ LEN ] = {0}; // 用于记录前一个数的索引 9 pre[0] = -1; 10 11 int states[LEN] = {0}; 12 states[0] = 1; 13 14 for(int i = 1; i < LEN; i++) // 这个for循环里面先不记录递增序列的全局最大值,最后统一搜索 15 { 16 pre[i] = -1; 17 for(int j = 0; j < i; j++) 18 { 19 if(num[i] > num[j]) 20 { 21 if(states[j] + 1 > states[i]) 22 { 23 states[i] = states[j] + 1; 24 pre[i] = j; 25 } 26 } 27 } 28 } 29 30 int max_subsequence = 1; 31 int max_index = 0; 32 for(int i = 0; i < LEN; i++) // 统一搜索最大值 33 { 34 if(states[i] > max_subsequence) 35 { 36 max_subsequence = states[i]; 37 max_index = i; 38 } 39 } 40 41 std::stack<int> s; 42 while(max_index != -1) 43 { 44 s.push(num[max_index]); 45 max_index = pre[max_index]; 46 } 47 48 std::cout << "max_subsequence : " << max_subsequence << std::endl; 49 50 std::cout << "subsequence : "; 51 while(!s.empty()) 52 { 53 std::cout << s.top() << " "; 54 s.pop(); 55 } 56 std::cout << std::endl; 57 58 return 0; 59 }
运行结果: