返回

算法进阶:LeetCode 769 - 最多能完成排序的块

后端

在计算机科学中,排序是一种基本算法,用于将一组元素按某种顺序排列。LeetCode 769 是一道颇具挑战性的算法题,它要求解决一个与排序相关的实际问题:在已排序的数组中,找到最多能完成多少次排序的块。

在本文中,我们将深入探讨 LeetCode 769 题解,并使用 Java、C++ 和 Rust 三种流行的编程语言提供详细的解决方案。此外,我们将深入了解这道题所涉及的类和方法,以增强我们的编程技能。

问题表述

给定一个已排序的数组 arr,其中可能包含一些相邻的重复元素,找出其中最多能完成多少次排序的块。所谓排序块,是指数组中连续的子数组,其元素按升序排列。

例如:

  • 对于 arr = [1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 7],最多能完成 6 次排序,因为有 [1, 2, 3], [4], [5], [5], [5, 5], [6, 7] 六个排序块。
  • 对于 arr = [1, 1, 2, 3, 4, 5, 6, 7, 8, 8],最多能完成 8 次排序,因为数组本身就是由 8 个排序块组成。
  • 对于 arr = [1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7],最多能完成 5 次排序,因为有 [1, 2, 3], [4], [5], [6], [7] 五个排序块。

Java 解决方案

import java.util.List;
import java.util.ArrayList;

class Solution {
    public int maxChunksToSorted(int[] arr) {
        int[] maxFromLeft = new int[arr.length];
        int[] minFromRight = new int[arr.length];

        maxFromLeft[0] = arr[0];
        for (int i = 1; i < arr.length; i++) {
            maxFromLeft[i] = Math.max(maxFromLeft[i - 1], arr[i]);
        }

        minFromRight[arr.length - 1] = arr[arr.length - 1];
        for (int i = arr.length - 2; i >= 0; i--) {
            minFromRight[i] = Math.min(minFromRight[i + 1], arr[i]);
        }

        int chunks = 0;
        for (int i = 0; i < arr.length; i++) {
            if (maxFromLeft[i] <= minFromRight[i]) {
                chunks++;
            }
        }

        return chunks;
    }
}

C++ 解决方案

#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    int maxChunksToSorted(vector<int>& arr) {
        vector<int> maxFromLeft(arr.size());
        vector<int> minFromRight(arr.size());

        maxFromLeft[0] = arr[0];
        for (int i = 1; i < arr.size(); i++) {
            maxFromLeft[i] = max(maxFromLeft[i - 1], arr[i]);
        }

        minFromRight[arr.size() - 1] = arr[arr.size() - 1];
        for (int i = arr.size() - 2; i >= 0; i--) {
            minFromRight[i] = min(minFromRight[i + 1], arr[i]);
        }

        int chunks = 0;
        for (int i = 0; i < arr.size(); i++) {
            if (maxFromLeft[i] <= minFromRight[i]) {
                chunks++;
            }
        }

        return chunks;
    }
};

Rust 解决方案

fn max_chunks_to_sorted(arr: &Vec<i32>) -> usize {
    let mut max_from_left: Vec<i32> = Vec::with_capacity(arr.len());
    let mut min_from_right: Vec<i32> = Vec::with_capacity(arr.len());

    max_from_left[0] = arr[0];
    for i in 1..arr.len() {
        max_from_left[i] = max_from_left[i - 1].max(arr[i]);
    }

    min_from_right[arr.len() - 1] = arr[arr.len() - 1];
    for i in (0..arr.len() - 1).rev() {
        min_from_right[i] = min_from_right[i + 1].min(arr[i]);
    }

    let mut chunks: usize = 0;
    for i in 0..arr.len() {
        if max_from_left[i] <= min_from_right[i] {
            chunks += 1;
        }
    }

    chunks
}

类和方法详解

Java

  • java.util.List:一个接口,表示一个有序集合。
  • java.util.ArrayList:一个实现了 List 接口的动态数组。
  • Math.max(a, b):返回 ab 中较大的一个。

C++

  • vector<int>:一个动态数组。
  • max(a, b):返回 ab 中较大的一个。
  • min(a, b):返回 ab 中较小的一个。

Rust

  • Vec<i32>:一个动态数组。
  • max_from_left[i].max(arr[i]):返回 max_from_left[i]arr[i] 中较大的一个。
  • min_from_right[i + 1].min(arr[i]):返回 min_from_right[i + 1]arr[i] 中较小的一个。

总结

LeetCode 769 是一道具有挑战性的算法题,需要我们运用排序、比较和数据结构的知识。通过使用 Java、C++ 和 Rust 三种流行的编程语言,我们提供了详细的解决方案,并深入了解了所使用的类和方法。通过练习和深入理解这些概念,我们可以提升自己的算法和编程能力。