返回
算法进阶:LeetCode 769 - 最多能完成排序的块
后端
2023-12-02 05:55:54
在计算机科学中,排序是一种基本算法,用于将一组元素按某种顺序排列。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)
:返回a
和b
中较大的一个。
C++
vector<int>
:一个动态数组。max(a, b)
:返回a
和b
中较大的一个。min(a, b)
:返回a
和b
中较小的一个。
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 三种流行的编程语言,我们提供了详细的解决方案,并深入了解了所使用的类和方法。通过练习和深入理解这些概念,我们可以提升自己的算法和编程能力。