最长递增子序列&&得到子序列的最少次数

基础:求一个序列的最长递增子序列
在这里插入图片描述
二分+贪心:
最长子序列的长度一定小于等于数组的长度,那么使用二分法,在遍历数组过程中,找到合适位置插入当前数据,如果当前查找位置比nums[i]小那么nums[i]应该放在当前位置的右侧,反之当前位置>=nums[i],那么右侧的范围应该缩小,使得当前较大位置数据替换成nums[i],如此我们可以得到最长递增子序列
在这里插入图片描述

class Solution {
    public int lengthOfLIS(int[] nums) {
    int []mm=new int[nums.length];
    int ans=0;
    for(int i=0;i<nums.length;i++){
        int left=0,right=ans;
        while(left<right){
            int mid=(right-left)/2+left;
            if(mm[mid]<nums[i])left=mid+1;
            else right=mid;
        }
        mm[left]=nums[i];
        if(left==ans)ans++;

    }
    return ans;
    }
}

进阶:求得是另外一个不重复序列为当前序列的子序列的最少操作次数?
在这里插入图片描述
有两种思路:
一种求得两个序列的最长子序列的长度len,然后用targe.length-len就为答案,但是源于此题设置数据长度太长,内存回超
第二种:
找出arr[]中 含有target的数,然后用list记录这些数在target的位置,那么由此转化为求得[0,1,2,3,4,5…](target各个数的位置)和list的最长公共子序列,[0,1,2,3,4,5…]是一个不重复的递增子序列,那么他们的最长公共子序列一定是递增序列同时,即为求得list的最长递增子序列长度len即可。结果即为target.length-len

class Solution {
    public int minOperations(int[] target, int[] arr) {
    Map<Integer,Integer> map=new HashMap<>();
    for(int i=0;i<target.length;i++){
        map.put(target[i],i);
    }
    List<Integer> list=new ArrayList<>();
    for(int i=0;i<arr.length;i++){
        if(map.containsKey(arr[i]))
        list.add(map.get(arr[i]));
    }
    int []num=new int[list.size()];
    int len=0;
    for(int i=0;i<list.size();i++){
        int left=0,right=len;
        while(left<right){
            int mid=(right-left)/2+left;
            if(num[mid]<list.get(i))
            left=mid+1;
            else right=mid;
        }
        num[left]=list.get(i);
        if(left==len)len++;
        
    }
    return target.length-len;
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值