当前位置: 首页 > article >正文

leetcode.1574 删除最短的子数组使剩余数组有序 - 阿里笔试 双指针 二分

1574. 删除最短的子数组使剩余数组有序

目录

1、双指针+二分 

2、双指针


题目:

给你一个数组a ,请你删除一个子数组(可以为空),使 a中剩下的元素是非递减的

一个子数组指的是原数组中连续的一个子序列

请你返回满足题目要求的最短子数组的长度

1、双指针+二分 

思路:

刚开始没动脑子,上来一个反向最长上升子序列直接wa

错误原因是:最长上升子序列选的是跳着选的,如果这么解部分样例会出现删除两个及以上的子数组,而题目要求删除一个连续子数组,所以dp是不对的

  • 先找出数组两端的最长非递减前缀和最长非递减后缀
  • res=min(删前缀,删后缀)
  • 枚举前缀的每一个点l作为最右端点
  • 对于每个l,二分找出在后缀里第一个≥arr[l]的下标r
  • 更新答案res=min(res,r-l-1)
class Solution {
    public int findLengthOfShortestSubarray(int[] arr) {
        int n=arr.length;
        //先找出数组两端的最长非递减前缀和最长非递减后缀
        int l=0,r=n-1;
        while(l+1<n&&arr[l]<=arr[l+1]) l++;
        while(r-1>=0&&arr[r]>=arr[r-1]) r--;
        if(l>=r) return 0; //如果最长非递减前后缀重叠 说明整个序列都是非递减
        

        int res=Math.min(r,n-1-l); //res=min(删前缀,删后缀)

        //枚举前缀的每一个点l作为最右端点
        //对于每个l,二分找出在后缀里第一个≥arr[l]的下标r
        //更新答案res=min(res,r-l-1),最短子数组就是区间[l+1,r-1] r-1-l-1+1=r-l-1
        for(int i=0;i<=l;i++)
        {
            int rr=search(arr,arr[i],r);
            res=Math.min(res,rr-i-1);
        }
        return res;
    }

    public int search(int[] arr,int target,int l)
    {
        int r=arr.length; //这里多设置1 是因为如果后缀中找不到≥arr[l]的数时 则删除的是整个后缀
        while(l<r)
        {
            int mid=l+r>>1;
            if(arr[mid]>=target) r=mid;
            else l=mid+1;
        }
        return l;
    }
}

2、双指针

思路:

  • 先找出数组两端的最长非递减前缀和最长非递减后缀 l和r
  • res=min(删前缀,删后缀)
  • 枚举前缀的每一个点l作为最右端点  用双指针在后缀中找到第一个比arr[l]大的数
  • 不断更新最小res=min(r-l-1)
class Solution {
    public int findLengthOfShortestSubarray(int[] arr) {
        int n=arr.length;
        //先找出数组两端的最长非递减前缀和最长非递减后缀
        int l=0,r=n-1;
        while(l+1<n&&arr[l]<=arr[l+1]) l++;
        while(r-1>=0&&arr[r]>=arr[r-1]) r--;
        if(l>=r) return 0;
        
        int res=Math.min(r,n-1-l);

        for(int i=0;i<=l;i++)
        {
            while(r<n&&arr[r]<arr[i]) r++;
            res=Math.min(res,r-i-1);
        }
        return res;
    }
}

 

这里不甘心非要放个我的最长上升子序列(误

class Solution {
    public int findLengthOfShortestSubarray(int[] arr) {
        int n=arr.length;
        int[] f=new int[n+1]; //f[i]以下标i为结尾的最长上升子序列长度

        for(int i=0;i<n;i++)
        {
            f[i]=1;
            for(int j=0;j<i;j++)
                if(arr[i]>=arr[j])
                    f[i]=Math.max(f[i],f[j]+1);
        }
        int res=-1;
        for(int i=0;i<n;i++) res=Math.max(res,f[i]);
        return n-res;
    }
}

 


http://www.kler.cn/a/3238.html

相关文章:

  • 27.收益的定义是什么?
  • 性能测试全链路监控模式有哪些?
  • 人工智能学习框架:深入解析与实战指南
  • Python从0到100(八十五):神经网络-使用迁移学习完成猫狗分类
  • java入门笔记基础语法篇(4)
  • 深度学习探索:ChatGPT数据分析精髓 梯度下降优化方法深度剖析
  • 清晰概括:进程与线程间的区别的联系
  • 两种方法教你在postman设置请求里带动态token
  • 入职第一天就被迫离职,找工作多月已读不回,面试拿不到offer我该怎么办?
  • MySQL数据库管理系统安装部署——Linux
  • Java 集合【学习笔记】Java 基础
  • 注意力机制(四):多头注意力
  • 冲击蓝桥杯-并查集,前缀和,字符串
  • Mysql查询优化_单表使用索引及常见索引失效
  • Linux编译cpprestsdk库
  • 菜鸟刷题Day6
  • 学习 Python 之 Pygame 开发魂斗罗(十三)
  • 邪恶的想法冒出,立马启动python实现美女通通下
  • vue更高效的工具-vite
  • nodejs的后端框架egg,thinkjs,nestjs,nuxtjs,nextjs对比
  • Spring Security实践
  • python自动发送邮件,qq邮箱、网易邮箱自动发送和回复
  • LeetCode-674. 最长连续递增序列
  • .NET Core 实现Excel的导入导出
  • 裸机条件下写一个基于时间片轮转的多任务并发程序
  • 动态内存管理(上)——“C”