最长公共子序列的O(n^2)与O(nlogn)求法(最长递增子序列的求法O(nlogn))

题目描述:给定两个数组A和B,A和B的元素相同,顺序不同,并且一个数组中的元素没有重复,删除最少的元素,使A和B元素个数与顺序相同。例如A={1,3,5,2},B={3,2,1,5},删除3和2之后A数组与B数组元素个数与顺序相同(元素个数小于100000)。

思路:找出A和B的最长公共子序列,删除其余元素即可。

需要注意的点:元素个数100000级别,如果写O(n^2)的最长公共子序列算法,时间太久,因此需要考虑O(nlogn)的算法。

 

解答:元素没有重复,因此可以转换为最长递增子序列求解,以下:

A数组映射为1,2,3,4,...;B数组根据A数组的映射关系转换(B元素在A数组中的位置);B数组计算最长递增子序列。

                                                

    //最长递增子序列
    public static int LIS(int[] A, int n) {
        int[] B = new int[n+1]; B[1] = A[0];
        int len=1,start=0,end=len,mid;
        for(int i = 1;i<n;i++){
            if(A[i]>B[len]) {len++;B[len] = A[i];}
            else{
                start=1;end=len;
                while(start<=end){
                    mid=(start+end)/2;
                    if(B[mid]<A[i]) start=mid+1;
                    else end=mid-1;
                } B[start] = A[i];
            }
        }
        return len;
    }

    //最长公共子序列
    public static int LCSNLogN(int[] A,int[] B, int n){
        if(A==null||A.length<=0||n<=0||A.length!=n) return 0;
        LinkedHashMap<Integer,Integer> mapDict=new LinkedHashMap<>();
        int[] data=new int[n];

        for(int i=0;i<n;i++){
            mapDict.put(A[i],i);
        }
        for(int i=0;i<n;i++){
            data[i]=mapDict.get(B[i]);
        }

        return LIS(data,n);
    }

 

另附:

LIS的代码借用这位老哥的博客中O(nlogn)的代码,如有不妥请联系删除:https://blog.csdn.net/karute/article/details/80761957

常规的动态规划O(n^2)算法:https://blog.csdn.net/qq_26567507/article/details/82712103

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值