LeetCode 颜色分类(Top 100):让你的算法技能亮起来
2023-11-01 08:56:08
算法揭秘:用 Swift 征服 LeetCode 中的经典颜色分类问题
简介
算法是编程世界中不可或缺的基础,而 LeetCode 是算法学习的圣殿,汇聚了海量经典算法题。其中,颜色分类算法(Top 100)更是重中之重。今天,让我们跟随算法大咖顾毅的步伐,使用 Swift 语言,一步步破解这道难题,点亮你的算法技能!
问题背景
假设我们有一个包含红色、白色和蓝色元素的数组,我们的任务是将这些元素分类,使相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
算法详解
1. 单指针法
单指针法是一种简单高效的解决方案。我们使用一个指针 i
遍历数组,同时维护两个边界指针 red
和 blue
,分别指向数组中第一个红色元素和最后一个蓝色元素。
当 i
指向红色元素时,我们将该元素与 red
指向的元素交换,并向前移动 red
指向;当 i
指向蓝色元素时,我们将该元素与 blue
指向的元素交换,并向后移动 blue
指向;当 i
指向白色元素时,我们直接向前移动 i
指向。
代码示例:
func sortColors(_ nums: inout [Int]) {
var i = 0, red = 0, blue = nums.count - 1
while i <= blue {
switch nums[i] {
case 0:
nums.swapAt(i, red)
red += 1
i += 1
case 1:
i += 1
case 2:
nums.swapAt(i, blue)
blue -= 1
default:
break
}
}
}
2. 双指针法
双指针法是一种更优雅的解决方案。我们使用两个指针 left
和 right
,分别指向数组中第一个蓝色元素和最后一个红色元素。
当 left
指向白色元素时,我们将该元素与 right
指向的元素交换,并向后移动 right
指向;当 right
指向红色元素时,我们将该元素与 left
指向的元素交换,并向前移动 left
指向;当 left
指向蓝色元素,right
指向红色元素时,我们直接向前移动 left
指向,并向后移动 right
指向。
代码示例:
func sortColors(_ nums: inout [Int]) {
var left = 0, right = nums.count - 1
for i in 0...right {
switch nums[i] {
case 0:
nums.swapAt(i, left)
left += 1
case 2:
nums.swapAt(i, right)
right -= 1
i -= 1 // 交换后 i 需回退一步,避免重复比较
default:
break
}
}
}
3. 三路快排法
三路快排法是一种更高级的解决方案。它将数组划分为三个区域:红色区域、白色区域和蓝色区域。我们使用两个指针 low
和 high
,分别指向红色区域的右边界和蓝色区域的左边界。
我们从头遍历数组,当遇到红色元素时,将其与 low
指向的元素交换,并将 low
指向的元素向前移动;当遇到蓝色元素时,将其与 high
指向的元素交换,并将 high
指向的元素向后移动;当遇到白色元素时,我们直接向前移动指针。
代码示例:
func sortColors(_ nums: inout [Int]) {
var low = 0, mid = 0, high = nums.count - 1
while mid <= high {
switch nums[mid] {
case 0:
nums.swapAt(low, mid)
low += 1
mid += 1
case 1:
mid += 1
case 2:
nums.swapAt(mid, high)
high -= 1
default:
break
}
}
}
实战演练
我们用一个例子来演示颜色分类算法的实际应用:
var nums = [2, 0, 2, 1, 1, 0]
sortColors(&nums)
print(nums) // 输出:[0, 0, 1, 1, 2, 2]
总结
颜色分类算法是算法学习中不可或缺的一部分,掌握这一算法有助于你提升算法技能。我们介绍了三种不同的解决方案,每一种都有其优缺点,你可以根据实际情况选择最适合你的方法。
算法之路永无止境,愿你不断探索,不断提升,成为一名算法大咖!
常见问题解答
1. 为什么单指针法中,遇到白色元素时不交换?
因为白色元素已经处于正确的位置,不需要交换。
2. 双指针法中,i -= 1
的作用是什么?
因为在交换红色元素和白色元素后,i
指向了红色元素,需要回退一步才能继续比较。
3. 三路快排法中,为什么白色元素不需要交换?
因为白色区域位于红色区域和蓝色区域之间,遇到白色元素时,指针 low
和 high
已经正确地将红色元素和蓝色元素交换到了它们应该在的位置。
4. 哪种算法更适合大规模数据?
三路快排法在时间复杂度上优于单指针法和双指针法,因此更适合处理大规模数据。
5. 除了颜色分类,还有什么其他问题可以用这些算法解决?
这些算法还可以用于解决荷兰国旗问题(将元素分类为红色、白色和蓝色)、三向归并排序(将数组中的元素分为三个部分:小于某个值、等于某个值和大于某个值)等问题。