diff --git a/src/SUMMARY.md b/src/SUMMARY.md index cc3f6fb8..30210a56 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -48,6 +48,7 @@ - [第二部分: 算法](algs/index.md) - [分析算法](algs-analysis/index.md) - [排序 Sorting](sorting/index.md) + - [排序相关的问题列表](leetcode/tags/sorting.md) - [查找](searching/index.md) - [二分查找 Binary Search](searching/binary-search/index.md) - [二分查找相关的问题列表](leetcode/tags/binary-search.md) @@ -90,6 +91,7 @@ - [链表](leetcode/tags/linked-list.md) - [数学](leetcode/tags/math.md) - [滑动窗口](leetcode/tags/sliding-window.md) + - [排序](leetcode/tags/sorting.md) - [栈](leetcode/tags/stack.md) - [字符串](leetcode/tags/string.md) - [双指针](leetcode/tags/two-pointers.md) @@ -101,6 +103,7 @@ - [0015. 三数之和 3Sum](leetcode/0015.3sum/index.md) - [0026. 删除有序数组中的重复项 Remove Duplicates from Sorted Array](leetcode/0026.remove-duplicates-from-sorted-array/index.md) - [0067. 二进制求和 Add Binary](leetcode/0067.add-binary/index.md) + - [0075. 颜色分类 Sort Colors](leetcode/0075.sort-colors/index.md) - [0080. 删除排序数组中的重复项 II Remove Duplicates from Sorted Array II](leetcode/0080.remove-duplicates-from-sorted-array-ii/index.md) - [0088. 合并两个有序数组 Merge Sorted Array](leetcode/0088.merge-sorted-array/index.md) - [0101-0200](leetcode/orders/0101-0200.md) diff --git a/src/leetcode/0075.sort-colors/assets/three-pointers.drawio b/src/leetcode/0075.sort-colors/assets/three-pointers.drawio new file mode 100644 index 00000000..c6fdf921 --- /dev/null +++ b/src/leetcode/0075.sort-colors/assets/three-pointers.drawio @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/leetcode/0075.sort-colors/index.md b/src/leetcode/0075.sort-colors/index.md new file mode 100644 index 00000000..69c2287b --- /dev/null +++ b/src/leetcode/0075.sort-colors/index.md @@ -0,0 +1,19 @@ +# 0075. 颜色分类 Sort Colors + +[问题描述](../problems/0075.sort-colors/content.html) + +## 靠拢型双指针 + +靠拢型双指针是一种常用方法, 这个解法是它的变体, 叫[DNF](../../two-pointers/close-up.md). + +```rust +{{#include src/main.rs:7:40 }} +``` + +## 排序法 + +各种常见的排序算法都可以, 比如括入排序, 选择排序. 因为这毕竟是一个排序题. + +```rust +{{#include src/main.rs:47:56 }} +``` \ No newline at end of file diff --git a/src/leetcode/0075.sort-colors/src/main.rs b/src/leetcode/0075.sort-colors/src/main.rs index 9bb5c525..b9d80cdc 100644 --- a/src/leetcode/0075.sort-colors/src/main.rs +++ b/src/leetcode/0075.sort-colors/src/main.rs @@ -4,19 +4,32 @@ #![allow(clippy::ptr_arg)] -pub fn sort_colors(nums: &mut Vec) { - let mut low = 0; +// 靠拢型双指针 +// Dutch National Flag, DNF +// three-way partition +pub fn sort_colors1(nums: &mut Vec) { + assert!(!nums.is_empty()); + + // 双指针的变形, 三指针 + // left 用于指向数组中为0的元素的右侧 + let mut left = 0; + // mid 用于遍历数组 let mut mid = 0; - let mut high = nums.len() - 1; - while mid <= high { + // right 用于指向数组中为2的元素的左侧 + let mut right = nums.len() - 1; + + // 遍历数组 + while mid <= right { if nums[mid] == 0 { - nums.swap(mid, low); - low += 1; + nums.swap(mid, left); mid += 1; + // 左边的指针往右移一下 + left += 1; } else if nums[mid] == 2 { - nums.swap(mid, high); - if high > 0 { - high -= 1; + nums.swap(mid, right); + // 右边的指针往左移一下 + if right > 0 { + right -= 1; } else { break; } @@ -26,20 +39,102 @@ pub fn sort_colors(nums: &mut Vec) { } } -fn check_solution() { +// 调用数组的排序方法, 这个不符合要求. +pub fn sort_colors2(nums: &mut Vec) { + nums.sort(); +} + +// 选择排序 Selection Sort +pub fn sort_colors3(nums: &mut Vec) { + for i in 0..(nums.len() - 1) { + for j in i..nums.len() { + if nums[i] > nums[j] { + nums.swap(i, j); + } + } + } +} + +// 插入排序 Insertion Sort +pub fn sort_colors4(nums: &mut Vec) { + for i in 1..nums.len() { + let mut j = i; + while j > 0 && nums[j - 1] > nums[j] { + nums.swap(j - 1, j); + j -= 1; + } + } +} + +// 冒泡排序 Bubble Sort +pub fn sort_colors5(nums: &mut Vec) { + for i in 0..(nums.len() - 1) { + let mut swapped = false; + for j in 0..(nums.len() - 1 - i) { + if nums[j] > nums[j + 1] { + nums.swap(j, j + 1); + swapped = true; + } + } + + if !swapped { + break; + } + } +} + +pub type SolutionFn = fn(&mut Vec); + +fn check_solution(func: SolutionFn) { let mut nums = vec![2, 0, 2, 1, 1, 0]; - sort_colors(&mut nums); + func(&mut nums); assert_eq!(&nums, &[0, 0, 1, 1, 2, 2]); let mut nums = vec![2, 2]; - sort_colors(&mut nums); + func(&mut nums); assert_eq!(&nums, &[2, 2]); let mut nums = vec![2]; - sort_colors(&mut nums); + func(&mut nums); assert_eq!(&nums, &[2]); } fn main() { - check_solution(); + check_solution(sort_colors1); + check_solution(sort_colors2); + check_solution(sort_colors3); + check_solution(sort_colors4); + check_solution(sort_colors5); +} + +#[cfg(test)] +mod tests { + use super::{ + check_solution, sort_colors1, sort_colors2, sort_colors3, sort_colors4, sort_colors5, + }; + + #[test] + fn test_sort_colors1() { + check_solution(sort_colors1); + } + + #[test] + fn test_sort_colors2() { + check_solution(sort_colors2); + } + + #[test] + fn test_sort_colors3() { + check_solution(sort_colors3); + } + + #[test] + fn test_sort_colors4() { + check_solution(sort_colors4); + } + + #[test] + fn test_sort_colors5() { + check_solution(sort_colors5); + } } diff --git a/src/leetcode/tags/sorting.md b/src/leetcode/tags/sorting.md new file mode 100644 index 00000000..b3489d9d --- /dev/null +++ b/src/leetcode/tags/sorting.md @@ -0,0 +1,9 @@ +# 排序 + +## 简单 + +## 中等 + +1. [0075. 颜色分类 Sort Colors](../0075.sort-colors/index.md) + +## 困难 \ No newline at end of file diff --git a/src/leetcode/tags/two-pointers.md b/src/leetcode/tags/two-pointers.md index aa02fd81..6907ee76 100644 --- a/src/leetcode/tags/two-pointers.md +++ b/src/leetcode/tags/two-pointers.md @@ -22,16 +22,16 @@ TODO: 1. [0011. 盛最多水的容器 Container With Most Water](../0011.container-with-most-water/index.md) 2. [0015. 三数之和 3Sum](../0015.3sum/index.md) -3. [0080. 删除排序数组中的重复项 II Remove Duplicates from Sorted Array II](../0080.remove-duplicates-from-sorted-array-ii/index.md) -4. [0167. 两数之和 II - 输入有序数组 Two Sum II - Input Array Is Sorted](../0167.two-sum-ii-input-array-is-sorted/index.md) -5. [0532.数组中的数对 K-diff Pairs in an Array](../0532.k-diff-pairs-in-an-array/index.md) +3. [0075. 颜色分类 Sort Colors](../0075.sort-colors/index.md) +4. [0080. 删除排序数组中的重复项 II Remove Duplicates from Sorted Array II](../0080.remove-duplicates-from-sorted-array-ii/index.md) +5. [0167. 两数之和 II - 输入有序数组 Two Sum II - Input Array Is Sorted](../0167.two-sum-ii-input-array-is-sorted/index.md) +6. [0532.数组中的数对 K-diff Pairs in an Array](../0532.k-diff-pairs-in-an-array/index.md) TODO: 1. [31. 下一个排列](https://leetcode.com/problems/next-permutation) -2. [75. 颜色分类](https://leetcode.com/problems/sort-colors) -3. [142. 环形链表 II](https://leetcode.com/problems/linked-list-cycle-ii) -4. [443. 压缩字符串](https://leetcode.com/problems/string-compression) -5. [524. 通过删除字母匹配到字典里最长单词](https://leetcode.com/problems/longest-word-in-dictionary-through-deleting) -6. [986. 区间列表的交集](https://leetcode.com/problems/interval-list-intersections) -7. [1498. 满足条件的子序列数目](https://leetcode.com/problems/number-of-subsequences-that-satisfy-the-given-sum-condition) +2. [142. 环形链表 II](https://leetcode.com/problems/linked-list-cycle-ii) +3. [443. 压缩字符串](https://leetcode.com/problems/string-compression) +4. [524. 通过删除字母匹配到字典里最长单词](https://leetcode.com/problems/longest-word-in-dictionary-through-deleting) +5. [986. 区间列表的交集](https://leetcode.com/problems/interval-list-intersections) +6. [1498. 满足条件的子序列数目](https://leetcode.com/problems/number-of-subsequences-that-satisfy-the-given-sum-condition) diff --git a/src/two-pointers/assets/Flag_of_the_Netherlands.svg b/src/two-pointers/assets/Flag_of_the_Netherlands.svg new file mode 100644 index 00000000..d17659fa --- /dev/null +++ b/src/two-pointers/assets/Flag_of_the_Netherlands.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/two-pointers/assets/sort-colors.rs b/src/two-pointers/assets/sort-colors.rs new file mode 120000 index 00000000..e1f0a79b --- /dev/null +++ b/src/two-pointers/assets/sort-colors.rs @@ -0,0 +1 @@ +../../leetcode/0075.sort-colors/src/main.rs \ No newline at end of file diff --git a/src/two-pointers/close-up.md b/src/two-pointers/close-up.md index 3ff68578..2025470c 100644 --- a/src/two-pointers/close-up.md +++ b/src/two-pointers/close-up.md @@ -11,6 +11,15 @@ - 根据题目要求, 选中左右两个指针中的一个, 往中间靠靠拢 (`left += 1` 或者 `right -= 1`, 另一个指针不动 - 直到循环中止 +## Dutch National Flag, DNF + +这是上面方法的一个变形, 可以查看问题 [0075. 颜色分类 Sort Colors](../leetcode/0075.sort-colors/index.md), +这个方法用于实现三路分区 (three-way partition). + +![The Dutch national flag](assets/Flag_of_the_Netherlands.svg) + +访问 [wikipedia](https://en.wikipedia.org/wiki/Dutch_national_flag_problem) 查看对应的介绍. + ## 相关问题 - [0011. 盛最多水的容器 Container With Most Water](../../leetcode/0011.container-with-most-water/index.md)