zoukankan      html  css  js  c++  java
  • LIS(最长上升子序列)

     这是O(n^2)的算法:

    #include<stdio.h>
    int main()
    {
        int n,i,k,max,lis[1001],num[1001];
        while(scanf("%d",&n)!=EOF)
        { 
            for(i=0;i<n;i++)
            {
                scanf("%d",&num[i]);
                lis[i]=1;
            }
            for(i=1;i<n;i++)
                for(k=0;k<i;k++)
                    if(num[k]<=num[i]&&lis[i]<lis[k]+1) //当前数比之前数大&&当前记录值≤之前记录值,这样,把当前记录值加一
                        lis[i]++;
            max=1;
            for(i=0;i<n;i++)
                if(max<lis[i])
                    max=lis[i];
            printf("%d\n",max);
        }
        return 0;
    }
    

    O(n*log2n)的算法:用到二分

    例如:

    lis[]中原先存入:1 5 7,再输入新数据num=3,则更新lis[1]=5为lis[1]=3,即求比num大的最小的lis[]中的数,进行替换。

    //求最长上升子序列 
    #include<stdio.h>
    int lis[40001]; 
    int binarysearch(int left,int right,int number) 
    { 
    	int mid; 
    	while(left<=right) 
    	{ 
    		mid=left+(right-left)/2; 
    		if(lis[mid]<number) left=mid+1; 
    		else right=mid-1; 
    	} 
    	return right; 
    } 
    int main() 
    { 
    	//freopen("input.txt","r",stdin); 
    	//freopen("output.txt","w",stdout); 
    	int n,p,i,tot,num,meet; 
    	while(scanf("%d",&n)!=EOF) 
    	{ 
    		while(n--) 
    		{ 
    			scanf("%d%d",&p,&num); 
    			lis[0]=num; 
    			tot=1; 
    			for(i=1;i<p;i++) 
    			{ 
    				scanf("%d",&num); 
    				if(num>lis[tot-1]) 
    					lis[tot++]=num; //如果num比lis[]末尾数大,则lis[]下标自增,存入num 
    				else if(num<lis[tot-1]) //如果num比lis[]末尾数小,则用二分法找到比num大的最小的数的下标,然后进行替换 
    				{ 
    					meet=binarysearch(0,tot-1,num); 
    					lis[meet+1]=num; 
    				} 
    			} 
    			printf("%d\n",tot); 
    		} 
    	} 
    	return 0; 
    }
    

    我还看到另一种用二分做的,还没想明白,继续研究

    //最长不下降子序列
    #include<stdio.h>
    int lis[1002]; 
    int binarysearch(int left, int right, int number) 
    { 
    	int mid; 
    	while(left<=right) 
    	{ 
    		mid=left+(right-left)/2; 
    		if(lis[mid]<=number) left=mid+1; //
    		else right=mid-1; 
    	} 
    	return left; 
    } 
    int main() 
    { 
    	int n,num,rightest,meet; 
    	while(scanf("%d", &n)!=EOF) 
    	{ 
    		lis[0]=-1; 
    		rightest=0; 
    		while(n--) 
    		{ 
    			scanf("%d",&num);
    			meet=binarysearch(0,rightest,num); //找到填入数据的位置
    			lis[meet]=num;
    			if(meet>rightest) //若返回的位置比原来的大,那么记录最右边位置的值加一
    				rightest++; 
    		} 
    		if (!rightest) 
    			rightest=1; 
    		printf("%d\n",rightest); 
    	} 
    }
    

      

  • 相关阅读:
    ASP.NET MVC Ajax下载文件(使用NPOI向现有的excel模板文件里面添加数据)
    Devexpress MVC DateEdit 设置默认的Time
    SQL 行转列(列的值不规则的数目)
    靶机Cyberry
    PHP-Audit-Labs-Day1
    DASCTF七月赛两道Web题复现
    靶机BlackMarket
    靶机CH4INRULZ_v1.0.1
    Kali中John的使用方法
    虚拟机中桥接模式和NAT模式以及仅主机模式的区别
  • 原文地址:https://www.cnblogs.com/submarinex/p/1941271.html
Copyright © 2011-2022 走看看