zoukankan      html  css  js  c++  java
  • 【100题】 第四十七题 序列的最长递增、递减序列

    一,题目

           求一个数组的最长递减子序列

                   比如{94325432}的最长递减子序列为{95432}

          

           求一个数组的最长递增子序列

                   比如{1,-1,2,-3,4,-5,6,-7}的最长递减子序列为{12436}

                 


    二,递增序列长度求解方法

           解法一:

                         时间复杂度为 o(n^2)

                         遍历数组序列,每遍历一个数组元素,则求序列到当前位置 最长的递增序列数,用temp[i]存储。

                         注意,当前的最长递增子序列受已经遍历的最长递增子序列影响,从序列头 再遍历到当前位置的前一个位置,挨个比较 a[j]与a[i](当前元素)大小,遇到小于a[i]且判断需要更新

    temp[]数组。

         由于这里仅仅是求,最长递增序列的长度,所以仅仅用temp[]存储长度大小。

                                                                                                                                                                            源码:

     

    #include <iostream>
    using namespace std;
    
    int LIS(int array[],int n)
    {
    	int temp[n];//存放当前遍历位置最长序列 
    	for(int i=0;i<n;++i)
    	{
    		temp[i]=1;   //初始化 默认长度 
    		for(int j=0;j<i;++j) //找出前面最长的序列 
    		{
    			// 当前值 array[i] 跟已经遍历的值比较,
    		    //大于已经遍历的值且已知递增序列+1 大于当前值则 更新当前最长递增序列值 
    			if(array[i]>array[j]  && temp[j]+1 > temp[i] )
    			{
    				temp[i] = temp[j] + 1;
    			}
    			
    		}
    	}
    	
    	int max=temp[0];
    	for(int k=0;k<n;++k)//找出整个数组中最长的子序列 
    	{
    		if(max<temp[k])
    			max=temp[k];
    	}
    	
    	return max;
    	
    }
    
    int main()
    {
    	int arr[]={1,-1,2,-3,4,-5,6,-7};
    	int result=LIS(arr,8);
    	cout<<result<<endl;
    	
    }
    

           解法二:时间复杂度任然为 O(n^2)

          为了减少比较次数

          采用空间换时间的策略。新增一个数组MaxV[],max[i]表示所有长度为i的递增子序列中最大值之间的最小值

          nMaxlax记录当前最长子序列

          每次遍历一个元素时候,从最长子序列开始遍历,一直到1 比较当前元素值arr[i] 跟MaxV[j]的值,从而更新temp[]最长子序列和nMaxLax和MaxV[]的值

      源码:

    #include <iostream>
    using namespace std;
    
    int LIS(int array[],int n)
    {
    	int temp[n];//存放当前遍历位置最长序列 
    	int  MaxV[n]; //最长子序列中最大值之间的最小值
    	MaxV[1]=array[0];//初始序列长度为1的子序列 中最大值的最小值
        MaxV[0]=-9999;//边界值
    	 
    	 for(int i=0;i<n;++i)
    	{
    		temp[i]=1;   //初始化 默认长度 
    	} 
    	 int  nMaxLis=1;
    	 int  j; 
    	for(int i=0;i<n;++i)
    	{
    		for(j=nMaxLis;j>=0;--j) //找出前面最长的序列 
    		{
    			if(array[i]>MaxV[j])//当前值大于长度为j的子序列中最大值之间的最小值 
    			{
    				temp[i] = j + 1;
    				break; 
    			}
    			
    		}
    		
    		if(temp[i]>nMaxLis)//在最长子序列时停止 (这时只有一个最长的) 
    		{
    			cout<<"nMaxLIs"<<nMaxLis<<endl; 
    			
    			nMaxLis=temp[i];
    			MaxV[temp[i]]=array[i]; 
    		} 
    		else if(MaxV[j] <array[i] && array[i]<MaxV[j+1])
    		{
    			MaxV[j+1]=array[i]; 
    		} 
    	}
    	
    	
    	return nMaxLis;
    	
    }
    
    int main()
    {
    	int arr[]={1,-1,2,-3,4,-5,6,-7};
    	int result=LIS(arr,8);
    	cout<<result<<endl;
    	
    }
    

      解法三:

          将内循环查询部分换成二分搜索,则时间复杂度降低为 O(nlogN)

                       

     

    三,递减序列 最长子序列求解方法

            用index数组,从大到小排序。然后依次遍历元素,查找元素在index数组中的位置pos ,根据位置来判断当前最长的子序列。

    #include<iostream>
    #include<cassert>
    #include<stack>
    using namespace std ;
    int BiSearch(int *A,int nTarget,int nLen);
    
    void FindLongestSequence(int *A,int nLen)
    {
    	int *index=new int[nLen];//存放子序列 
    	int *LDS=new int[nLen];
    	
    	index[0]=A[0];
    	LDS[0]=1;
    	int indexLen=1; //最长递增子序列 长度 
    	
    	for (int i=1;i<nLen;i++)
    	{
    		//这里是关键,在已经加入的 序列中查找当前序列的插入位置
    		 
    		int pos=BiSearch(index,A[i],indexLen);
    		
    		index[pos]=A[i];
    		LDS[i]=pos+1;//记录当前最长序列
    		 
    		if(pos>=indexLen)//插入的当前位置大于最长序列 
    			indexLen++;
    	}
    	
    	int ResultLen=indexLen;
    	for (int i=nLen;i>=0;i--)//记录最长递减子序列 
    	{
    		if(LDS[i]==ResultLen)
    		{	
    			index[ResultLen-1]=A[i];
    			ResultLen--;
    		}		
    	}
    
    	for (int i=0;i<indexLen;i++)
    	{
    		cout<<index[i]<<" ";
    	}
    	delete []index;
    
    }
    int BiSearch(int *A,int nTarget,int nLen)//二分搜索 
    {
    	assert(A!=NULL&&nLen>0);
    	int start=0;
    	int end=nLen-1;
    	while (start<=end)
    	{
    		int mid=(start+end)/2;
    		if(nTarget>A[mid])
    			end=mid-1;
    		else if(nTarget<A[mid])
    			start=mid+1;
    		else
    			return mid;
    	}
    	return start;
    }
    int main()
    {
    	int A[]={9,4,3,2,5,4,3,2,77,76};
    	int nLen=sizeof(A)/sizeof(int);
    	FindLongestSequence(A,nLen);
    	return 1;
    }


     


     

  • 相关阅读:
    kubenetes-学习
    k8s-字段
    Spring Boot集成mongodb
    synchronized关键字
    Scala手记
    Python数据结构&封装解构
    Scala基础之集合
    Scala基础之集合常用方法
    Scala(2.12)之collection基本操作
    Scala基础之集合(数组)
  • 原文地址:https://www.cnblogs.com/secbook/p/2654960.html
Copyright © 2011-2022 走看看