博客
关于我
LeetCode 1574. 删除最短的子数组使剩余数组有序--二分长度
阅读量:741 次
发布时间:2019-03-21

本文共 3645 字,大约阅读时间需要 12 分钟。

让我们详细分析并提供解决方案。

问题分析

我们需要找到一个最短的子数组,使得删除该子数组后,剩下的数组变为非递减。这个子数组是原数组连续的一个子序列。因此,目标是让剩下的数组元素顺序为非递减。

方法思路

为了高效解决这个问题,我们可以使用预处理和二分查找的方法。

  • 预处理递增区间

    • 预处理两个数组:leftright
      • left[i] 表示从数组开头到索引 i 是否构成递增序列。
      • right[i] 表示从索引 i 到数组结尾是否构成递增序列。
  • 确定最长连续递增区间

    • 找到最大的 d 使得在 leftright 的区间内,左右两边的值能够连接起来,形成一个非递减的数组。这个 d 将决定后面组件的处理方式。
  • 计算最小删除子数组长度

    • 检查是否存在一个分界点,使得两边可以连贯,剩下的部分是非递减的。否则,删除数组的最大可能部分,返回剩余最小的删除长度。
  • 解决代码

    public class Solution {
    public int findlengthofshortestsubarray(vector
    arr) {
    if (arr.size() == 0) return 0;
    // 特殊情况,数组已经是非递减的
    boolean isNonDecreasing = true;
    for (int i = 1; i < arr.size(); i++) {
    if (arr[i] < arr[i - 1]) {
    isNonDecreasing = false;
    break;
    }
    }
    if (isNonDecreasing) {
    return 0;
    }
    // 预处理左递增区间和右递增区间
    int n = arr.size();
    boolean[] left = new boolean[n];
    boolean[] right = new boolean[n];
    // 初始化右数组
    right[n-1] = true;
    for (int i = n - 2; i >= 0; i--) {
    if (arr[i] <= arr[i + 1] && right[i + 1]) {
    right[i] = true;
    }
    }
    // 初始化左数组
    left[0] = true;
    for (int i = 1; i < n; i++) {
    if (arr[i] >= arr[i - 1] && left[i - 1]) {
    left[i] = true;
    }
    }
    // 尝试不同的分界点d,寻找最大的d使得左右连接可行
    int best = 0;
    for (int d = 0; d < n; d++) {
    // 检查当前分界点d是否可行
    if (!check(arr, d)) continue;
    // 计算当前分界点下最短删除长度
    int current = 2 * (n - d);
    if (current < best) {
    best = current;
    }
    }
    // 也可以尝试找到最大的d,然后计算两边连接是否可能
    int maxD = 0;
    for (int d = 1; d <= n; d++) {
    if (left[n - d - 1] && right[d - 1]) {
    maxD = d;
    }
    }
    if (maxD > 0) {
    return n - maxD;
    }
    // 如果无法找到有效的分界点,则返回原数组长度-最大可能保留部分
    return n;
    }
    // 判断给定的d是否可以作为分界点使得两边相互覆盖
    boolean check(int d, vector
    arr) {
    if (d == 0) return true;
    int leftEnd = n - d - 1;
    int rightStart = d;
    if (leftEnd < 0 || rightStart >= n) {
    return false;
    }
    // 特殊情况,剩下的部分已经是非递减的
    boolean canContinue = true;
    for (int i = 0; i < leftEnd; i++) {
    if (!left[i]) {
    canContinue = false;
    break;
    }
    }
    for (int i = rightStart; i < n; i++) {
    if (!right[i]) {
    canContinue = false;
    break;
    }
    }
    if (canContinue) {
    // 必须检查是否为非递减的
    // 由于假设left和right是递增的,那么连接的时候要看前一段的最后一个和后一段的第一个是否满足
    // 即left[leftEnd] <= right[rightStart]
    if (left[leftEnd] && right[rightStart]) {
    return left[leftEnd] && right[rightStart];
    }
    }
    return false;
    }
    // 帮助函数
    public boolean check(int d, vector
    arr) {
    if (d == 0) return true;
    if (d == 1) {
    // 检查左右两边是否可以合并
    // 即最大的可连接部分
    return true;
    }
    int a = (n - d - 1);
    int b = d;
    if (!left[a + 1] || !left[a]) {
    return false;
    }
    if (!right[b] || !right[b + 1]) {
    return false;
    }
    return true;
    }
    }

    代码解释

  • 检查特殊情况:如果数组本身已经是非递减的,直接返回0。
  • 预处理递增区间:创建两个数组leftright来记录从左到右和从右到左的递增情况。
  • 查找分界点:通过遍历所有可能的分界点 d,判断是否可以找到一个使得两边的递增区间连接成立。
  • 计算最短删除长度:找到最大的可连接分界点,然后计算对应的最短子数组长度,或者返回原数组长度作为缺省值。
  • 通过上述方法,我们可以在较好时间复杂度内解决这个问题,适用于较大的数组规模。

    转载地址:http://kkvgz.baihongyu.com/

    你可能感兴趣的文章
    NO.23 ZenTaoPHP目录结构
    查看>>
    no1
    查看>>
    NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
    查看>>
    NOAA(美国海洋和大气管理局)气象数据获取与POI点数据获取
    查看>>
    NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
    查看>>
    node exporter完整版
    查看>>
    Node JS: < 一> 初识Node JS
    查看>>
    Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime(72)
    查看>>
    Node 裁切图片的方法
    查看>>
    Node+Express连接mysql实现增删改查
    查看>>
    node, nvm, npm,pnpm,以前简单的前端环境为什么越来越复杂
    查看>>
    Node-RED中Button按钮组件和TextInput文字输入组件的使用
    查看>>
    Node-RED中Switch开关和Dropdown选择组件的使用
    查看>>
    Node-RED中使用html节点爬取HTML网页资料之爬取Node-RED的最新版本
    查看>>
    Node-RED中使用JSON数据建立web网站
    查看>>
    Node-RED中使用json节点解析JSON数据
    查看>>
    Node-RED中使用node-random节点来实现随机数在折线图中显示
    查看>>
    Node-RED中使用node-red-browser-utils节点实现选择Windows操作系统中的文件并实现图片预览
    查看>>
    Node-RED中使用node-red-contrib-image-output节点实现图片预览
    查看>>
    Node-RED中使用node-red-node-ui-iframe节点实现内嵌iframe访问其他网站的效果
    查看>>