颜色分类 力扣第75题 : https://leetcode-cn.com/problems/sort-colors/
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意: 不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0] 输出: [0,0,1,1,2,2]
1. 计数排序 这道题其实说白了就是排序,可以按照普通的排序直接做,但是它这里只会出现0, 1, 2 这三种数字,所以使用计数排序是一个很好的选择。
1 2 3 4 5 6 7 8 9 10 11 class Solution : def sortColors (self, nums: List[int]) -> None : bucket = [0 ] * 3 sorted_index = 0 for num in nums: bucket[num] += 1 for index, count in enumerate(bucket): while count > 0 : nums[sorted_index] = index sorted_index += 1 count -= 1
复杂度分析 时间复杂度: 扫描一遍数组算出各个数字的次数,时间复杂度为O(N),然后在重写数组,所以总的时间为O(N)
空间复杂度: 用了一个列表来作为桶,长度为3,所以空间复杂度为O(1)
2. 一次遍历 因为只有0, 1, 2 这三个数字,所以0肯定为最左边,2为最右边,我们使用两个指针,一个指向左,一个指向右边,当我们遍历数组时,如果当前数位0,则将其与左边的数交换,如果为2就和右边的数交换。我后来看了题解,是叫荷兰国旗问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution : def sortColors (self, nums: List[int]) -> None : """ Do not return anything, modify nums in-place instead. """ head, tail = 0 , len(nums) - 1 index = 0 while index <= tail: if nums[index] == 0 : nums[head], nums[index] = nums[index], nums[head] head += 1 index += 1 elif nums[index] == 2 : nums[tail], nums[index] = nums[index], nums[tail] tail -= 1 else : index += 1
复杂度分析 时间复杂度: 由于对长度 N 的数组进行了一次遍历,时间复杂度为O(N)。
空间复杂度: 用了一个列表来作为桶,长度为3,所以空间复杂度为O(1)。
3. 三路快排
参考自 https://leetcode-cn.com/problems/sort-colors/solution/kuai-su-pai-xu-partition-guo-cheng-she-ji-xun-huan/ 作者:liweiwei1419
如果循环不变量是这样定义的: 所有在子区间 [0, zero) 的元素都等于 0; 所有在子区间 [zero, i) 的元素都等于 1; 所有在子区间 [two, len - 1] 的元素都等于 2。
编码的时候,zero 和 two 初始化的值就应该保证上面的三个子区间全为空。
在遍历的过程中,“索引先加减再交换”、还是“先交换再加减”就看初始化的时候变量在哪里。
退出循环的条件也看上面定义的循环不变量,在 i == two 成立的时候,上面的三个子区间就正好“不重不漏”地覆盖了整个数组,并且给出的性质成立,题目的任务也就完成了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 from typing import Listclass Solution : def sortColors (self, nums: List[int]) -> None : """ Do not return anything, modify nums in-place instead. """ def swap (nums, index1, index2) : nums[index1], nums[index2] = nums[index2], nums[index1] size = len(nums) if size < 2 : return zero = 0 two = size i = 0 while i < two: if nums[i] == 0 : swap(nums, i, zero) i += 1 zero += 1 elif nums[i] == 1 : i += 1 else : two -= 1 swap(nums, i, two)