最长递增子序列动态规划求解和利用二分查找去优化动态规划,优化成n*logn

自从保研后,就找个兼职做财务,闲的时候就看各种技术贴和面经,发现想进大型互联网公司,算法和数据结构就必须过关了。借用左神说的,国内好公司爱考算法和数据结构,国外互联网公司几乎只考算法和数据结构。所以我就决定好好刷算法了。

上题了:给定数组arr,返回arr的最长递增子序列。

解法一:常规的dp。

#include <stdio.h>
int main()
{
	int n, max, m, k;
	scanf("%d", &n);
	int a[n], dp[n], b[n]; 			//a[i]表示序列,dp[i]表示以数组第i个数结尾时最长的递增子序列 
	for(int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		dp[i] = 1; 				//初始化dp数组 
	}
	for(int i = 1; i < n; i++)
	{
		for(int j = 0; j < i; j++)
		{
			if(a[i] > a[j] && dp[i] < dp[j] + 1)	//	O(N^2)复杂度主要在这里面的穷举
			dp[i] = dp[j] + 1; 
		}
	}
	max = dp[0];
	for(int i = 1; i < n; i++)						//去找到dp数组里面最大的值 
	{
		if(max < dp[i])
		{
			max = dp[i];
			 m = i;									//同时记录下最大dp在数组中的下标 
		} 
	}
	k = max;
	printf("%d\n", max); 
	b[max] = a[m];
	for(int i = m-1; i > 0; i--)			//输出最长递增子序列,从后往前推满足此条件a[m] > a[m-1] && dp[m] = dp[i] + 1
	{
		if(a[m] > a[i] && dp[m] == dp[i] + 1)
		{
			b[--max] = a[i];
			m = i;
		}
	}
	for(int i = 1; i <= k; i++)
	printf("%d ",b[i]);
	return 0;
}


解法二:利用二分查找去加快穷举的速度,说白了就是以每个数结尾的最长递增子序列能放在哪

#include <stdio.h>

int binary_search(int c[], int l, int h, int key) 	//找到从左到右,第一个比它大的数的位置,多种思路 
{
	int mid;
	while(l < h)
	{
		mid = l + (h-l)/2;
		if(key <= c[mid])
		l = mid + 1;
		else
		h = mid;								//因为比它大,所以不能跳过 
	}
	return l;
}

int main()
{
	int n, max, m, k, len = 0, pos;
	scanf("%d", &n);
	int a[n], dp[n], b[n], h[n]; 			//a[i]表示序列,dp[i]表示以数组第i个数结尾时最长的递增子序列 
	for(int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		dp[i] = 1; 				//初始化dp数组 
	}
	h[len] = a[0];
	for(int i = 1; i < n; i++)
	{
		if(a[i] > h[len])
		{
			h[++len] = a[i];
			dp[i] = len + 1;
		}
		else
		{
			pos = binary_search(a,0,len,a[i]);
			h[pos] = a[i];
			dp[i] = pos + 1; 
		}
	}
	max = dp[0];
	for(int i = 1; i < n; i++)						//去找到dp数组里面最大的值 
	{
		if(max < dp[i])
		{
			max = dp[i];								//同时记录下最大dp在数组中的下标 
			m = i;
		} 
	}
	k = max;
	printf("%d\n", max); 
	b[max] = a[m];
	for(int i = m-1; i > 0; i--)			//输出最长递增子序列,从后往前推满足此条件a[m] > a[m-1] && dp[m] = dp[i] + 1
	{
		if(a[m] > a[i] && dp[m] == dp[i] + 1)
		{
			b[--max] = a[i];
			m = i;
		}
	}
	for(int i = 1; i <= k; i++)
	printf("%d ",b[i]);
	return 0;
}

对比下两者运行时间就知道了。下一题是最长公共子序列。我正在看这题,等理解透彻了,也写个博客。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值