算法设计与分析入门篇----动态规划 1

正在网易云课堂学习王宏志老师的算法设计与分析入门篇课程视频,将学习中的作业问题发上来与大家一同讨论。这篇是对第四周的作业第一题个人的一些思路,希望与大家一同学习。


题目内容:

给定有 n 个整数组成的数列 {A_n},记为:A_1、A_2、……、A_n。

A 的一个不降子序列,为 {B_m},满足 1<= B_i <= n 且对于所有的 1 <= i < m,满足:

Bi < B_{i+1},并且 A_{B_i} <= A_{B_{i+1}}。

例如 {A_n} = 3,18,7,14,10,12,23,41,16,24。

如上例中 3,18,23,24 就是一个长度为 4 的不下降序列,同时也有 3,7,10,12,16,24 长度为 6 的不下降序列。

求所有 {A_n} 的不降子序列中,最长的长度。


输入格式:

输入数据的第一行包含一个整数 n。(1\leq n \leq 10^5)

接下来的一行,包含 n 个整数 A_i。(1\leq A_i \leq 10^9)


输出格式:

输出一行表示答案。


输入样例:



输出样例:


时间限制:2000ms内存限制:128000kb

比较坑,没明确说明输出个数还是数组。

思路:记录从1到max(最长长度)所有子序列的最末位数,然后不断用更小的数更新。

如:6 12 8 1 9 4 3 6 7 8 10

第一次读入6, 

长度 1 2 3 4 5 6 7
末尾数 6            

读入12,

长度 1 2 3 4 5 6 7
末尾数 6 12          

读入8,

长度 1 2 3 4 5 6 7
末尾数 6 8          

长度为2的不降子序列末尾最小为8,子序列为 6,8


读入1,

长度 1 2 3 4 5 6 7
末尾数 1 8          

长度为1的不降子序列末尾最小为1,子序列为 1,


读入9,

长度 1 2 3 4 5 6 7
末尾数 1 8 9        

最长不降子序列长度加1,子序列为 1,8,9


读入4,

长度 1 2 3 4 5 6 7
末尾数 1 4 9        

长度为2的不降子序列末尾最小为4,子序列为  1,4


读入3,

长度 1 2 3 4 5 6 7
末尾数 1 3 9        

长度为2的不降子序列末尾最小为3,子序列为  1,3


读入6,

长度 1 2 3 4 5 6 7
末尾数 1 3 6        

长度为3的不降子序列末尾最小为6,子序列为  1,3,6


读入7,

长度 1 2 3 4 5 6 7
末尾数 1 3 6 7      

最长不降子序列长度加1,子序列为 1,3,6,7


读入8,

长度 1 2 3 4 5 6 7
末尾数 1 3 6 7 8    

最长不降子序列长度加1,子序列为 1,3,6,7,8



读入10,

长度 1 2 3 4 5 6 7
末尾数 1 3 6 7 8 10  

最长不降子序列长度加1,子序列为 1,3,6,7,8,10


代码如下:

int max = 1;
d[0] = p[0];
for (int i = 1; i < n; i++){
int j = 0;
for (; j < max; j++){
if (p[i] < d[j]){
d[j] = p[i];
break;
}
}
if (j == max){
d[max] = p[i];
max++;
}
}

cout << max<<"\r\n";



这是不要求输出子列内容的,时间复杂度为 n^2。如果要求输出子列内容,则可以开一个n*n的二维数组,记录路径。不过,每次最长不降子序列长度加1是,都要拷贝路径,时间复杂度就要达到 n^3。


动态规划使用循环与递归都可以实现,循环的效率能更高一点。但不是说循环比递归好,用什么方法,全凭个人兴趣。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值