最长递增子序列

最长递增子序列

第一种是纯用动态规划的O(n2)的方法

dp[i] 表示0~i的最长递增序列的长度
思路:对于每个i,都向前面寻找dp[j]以及num[j]最大且num[j] < num[i]的j, 然后进行状态转移,从长度为2 到 n,依次遍历即可

个人认为该方式不太像动态规划 hhh

然后附上代码:

	static int[] num = new int[100000];
	static int[] dp = new int[100000];
	static void longestDp() {
		int res = 0;
		dp[1] = 1;
		for(int i = 2; i <= n; i++) {
			int len = 0;
			for(int j = 1; j < i; j++) {
				if(num[j] < num[i] && len < dp[j])
					len = dp[j];
			}
			dp[i] = len + 1;
			res = dp[i] > res?dp[i]:res;
		}
		System.out.println(res);
	}

第二种是可以达到O(nlogn)的复杂度的算法
多用了O(n)的空间复杂度
新建了个辅助数组help, help[i]表示, i 长度的递增子序列,末尾最小值为help[i]

思路:如果大于help[helpLen]的话,直接插入后面并令helpLen++,否则给num[i]找到它所在的位置,然后最后结果helpLen就是为最长递增子序列的答案。。

然后因为每次都要为i找到它的容身之所的话,那么最好的方法就是二分了

ps:如果是求子序列而不是求长度的话这种方法得进行适当的修改

然后附上代码:

	static int[] num = new int[100000];
	static int[] dp1 =new int[100000];
	static int[] help = new int[10000];		//help数组来解决最后一种nlogn的方法
	static int helpLen = 0;					//help数组的长度
	static int dichotomy(int l, int r, int i) {		//辅助的二分函数
		if(l == r)
			return l;
		int mid = (r-l)/2+l;
		if(help[mid] > num[i])
			return dichotomy(l, mid, i);
		else if(help[mid] < num[i])
			return dichotomy(mid+1, r, i);
		else
			return mid;
	}
	static void longestDp1() {					//二分+dp
		for(int i = 1; i <= n; i++) {
			if(num[i] > help[helpLen]) {
				help[++helpLen] = num[i];
			}else {
				int index = dichotomy(1, helpLen, i);
				help[index] = num[i];
			}
		}
		System.out.println(helpLen);
	}

思路有参考别人的,但代码纯自己重新写,不喜勿喷

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值