解题思路

我们需要找到一个无序数组中需要排序的最短子数组的长度。关键在于确定这个子数组的起始和结束位置。

算法步骤:

  1. 找到无序的边界

    • 从左到右遍历数组,找到第一个不满足升序的元素,记为left
    • 从右到左遍历数组,找到第一个不满足升序的元素,记为right
  2. 确定最小和最大值

    • leftright之间的子数组中,找到最小值和最大值。
  3. 扩展边界

    • 如果最小值小于left位置的元素,更新left
    • 如果最大值大于right位置的元素,更新right
  4. 计算长度

    • 返回right - left + 1作为需要排序的最短子数组的长度。

代码

import java.util.*;


public class ShortSubsequence {
    public int findShortest(int[] A, int n) {
        if (n <= 1) return 0;

        int left = 0, right = n - 1;

        // 找到第一个不满足升序的元素
        while (left < n - 1 && A[left] <= A[left + 1]) {
            left++;
        }

        // 如果整个数组是有序的
        if (left == n - 1) return 0;

        // 找到最后一个不满足升序的元素
        while (right > 0 && A[right] >= A[right - 1]) {
            right--;
        }

        // 在[left, right]之间找到最小值和最大值
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        for (int i = left; i <= right; i++) {
            if (A[i] < min) min = A[i];
            if (A[i] > max) max = A[i];
        }

        // 扩展left和right边界
        while (left > 0 && A[left - 1] > min) {
            left--;
        }
        while (right < n - 1 && A[right + 1] < max) {
            right++;
        }

        return right - left + 1;  // 返回需要排序的最短子数组的长度
    }

    public static void main(String[] args) {
        ShortSubsequence ss = new ShortSubsequence();
        int[] A = {1, 5, 3, 4, 2, 6, 7};
        int result = ss.findShortest(A, A.length);
        System.out.println(result);  // 输出 4
    }
}
class ShortSubsequence {
public:
    int findShortest(vector<int>& A) {
        int n = A.size();
        if (n <= 1) return 0;

        int left = 0, right = n - 1;

        // 找到第一个不满足升序的元素
        while (left < n - 1 && A[left] <= A[left + 1]) {
            left++;
        }

        // 如果整个数组是有序的
        if (left == n - 1) return 0;

        // 找到最后一个不满足升序的元素
        while (right > 0 && A[right] >= A[right - 1]) {
            right--;
        }

        // 在[left, right]之间找到最小值和最大值
        int min = INT_MAX;
        int max = INT_MIN;
        for (int i = left; i <= right; i++) {
            if (A[i] < min) min = A[i];
            if (A[i] > max) max = A[i];
        }

        // 扩展left和right边界
        while (left > 0 && A[left - 1] > min) {
            left--;
        }
        while (right < n - 1 && A[right + 1] < max) {
            right++;
        }

        return right - left + 1;  // 返回需要排序的最短子数组的长度
    }
};
# -*- coding: utf-8 -*-

class ShortSubsequence:
    def findShortest(self, A, n):
        if n <= 1:
            return 0

        left, right = 0, n - 1

        # 找到第一个不满足升序的元素
        while left < n - 1 and A[left] <= A[left + 1]:
            left += 1

        # 如果整个数组是有序的
        if left == n - 1:
            return 0

        # 找到最后一个不满足升序的元素
        while right > 0 and A[right] >= A[right - 1]:
            right -= 1

        # 在[left, right]之间找到最小值和最大值
        min_val = float('inf')
        max_val = float('-inf')
        for i in xrange(left, right + 1):
            if A[i] < min_val:
                min_val = A[i]
            if A[i] > max_val:
                max_val = A[i]

        # 扩展left和right边界
        while left > 0 and A[left - 1] > min_val:
            left -= 1
        while right < n - 1 and A[right + 1] < max_val:
            right += 1

        return right - left + 1  # 返回需要排序的最短子数组的长度




算法及复杂度

  • 算法:通过边界查找确定最短子数组
  • 时间复杂度:,遍历数组几次
  • 空间复杂度:,只使用常数额外空间