Leetcode 300: 最长递增子序列

题目

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

解法

注意:子序列,不要求连续
解法一:傻叉解法,比较好想
思路是:设置一个数组dp,dp[i]表示,以i位置结尾的最长递增子序列
转移方程是:dp[i] = max(dp[j] + 1) (array[j] < array[i] && j < i)

	public static int maxIncreaseSubarray2(int[] array) {
		// 傻逼解法
		if(array == null || array.length == 0) return 0;
		int ans = 1;
		int len = array.length;
		int[] memo = new int[len];
		Arrays.fill(memo, 1);
		// 以每个位置结尾的最长递增子序列
		for(int i = 1; i < len; i++) {
			for(int j = 0; j < i; j++) {
				if(array[i] > array[j])
					memo[i] = Math.max(memo[i], memo[j] + 1);
			}
			ans = Math.max(ans, memo[i]);
		}
		return ans;
	}

解法二:排序后,找最长公共子序列
不解释;虽然我也想不到

	public static int maxIncreaseSubarray(int[] array) {
		// 解法二:排序后,找最长公共子序列
		int[] copy = Arrays.copyOf(array, array.length);
		Arrays.sort(copy);
		// 复习一下求最长公共子序列的方法= =
		int len = copy.length;
		int[][] dp = new int[len][len];
		dp[0][0] = copy[0] == array[0] ? 1 : 0;
		for(int i = 1; i < len; i++) {
			dp[0][i] = copy[0] == array[i] ? 1 : dp[0][i - 1];
		}
		for(int i = 1; i < len; i++) {
			dp[i][0] = copy[i] == array[0] ? 1 : dp[i - 1][0];
		}
		for(int i = 1; i < len; i++) {
			for(int j = 1; j < len; j++) {
				if(copy[i] == array[j]) {
					dp[i][j] = dp[i - 1][j - 1] + 1;
				}else {
					dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
				}
			}
		}
		return dp[len - 1][len - 1];
		
	}

解法三:
参考:https://blog.csdn.net/love20165104027/article/details/79618367
思路:设置一个数组tail, (假设从1开始)tail[i]表示最长递增子序列长度为i时,最小的结尾元素。
再解释:就是,在数组array中,找递增子序列,可能找到长度为2的若干递增子序列;那么tail[2] 就表示,这些子序列中,第二个元素(最后一个元素)最小的那个值。
遍历数组,

  • 如果当前位置j,的元素cur,大于tail数组的最后一个元素tail[k](也就是说,存在k+1长度的递增子序列),将该元素加入tail尾部;
  • 如果当前元素cur,小于tail数组的最后一个元素tail[k](也就是说,不能直接接在后面),则在tail数组中找刚好大于cur的元素位置为l,值为ele,即ele大于cur,而ele前面的元素小于cur。表示:长度为l的递增子序列,其最小值可以为cur。用cur替换l位置的值ele。
    遍历到最后,tail数组的长度,就是最长递增子序列的长度。
    Note: tail数组并不是最长递增子序列!
    就……迷迷糊糊,似懂非懂?
	public static int maxIncreaseSubarray(int[] array) {
		if(array == null || array.length <= 0) return 0;
		int len = array.length;
		int[] tail = new int[len];
		int size = 0;
		tail[0] = array[0];
		for(int i = 1; i < len; i++) {
			if(array[i] > tail[size]) {
				tail[++size] = array[i];
			}else {
				// 这里可以用二分查找,优化时间
				int j;
				for(j = size - 1; j >= 0; j--) {
					if(array[i] > tail[j]) {
						break;
					}
				}
				tail[j + 1] = array[i];
			}
		}
		return size + 1;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值