LeetCode 分类颜色

LeetCode   分类颜色

给定一个包含红色、白色和蓝色,一共 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

进阶:

    • 一个直观的解决方案是使用计数排序的两趟扫描算法。
      首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
    • 你能想出一个仅使用常数空间的一趟扫描算法吗?

1.   使用基数排序:

 1 class Solution:
 2     def sortColors(self, nums):
 3         """
 4         :type nums: List[int]
 5         :rtype: void Do not return anything, modify nums in-place instead.
 6         """
 7         #桶排序
 8         count = []
 9         for i in [0,1,2]:
10             count.append(nums.count(i))
11         j=0
12         for i in [0,1,2]:
13             while count[i]>0:
14                 nums[j] = i
15                 j += 1
16                 count[i] -= 1
17         print(nums)

 

2.    使用快排:

两路快排的Partition的实现(c++):

1 // v为pivot,初始存储在arr[l]的位置 
2 int j = l; // 循环过程保持 arr[l+1...j] < v ; arr[j+1...i) > v 
3 for( int i = l + 1 ; i <= r ; i ++ )
4     if( arr[i] < v ) 
5         swap( arr[++j] , arr[i] );
6 swap( arr[l] , arr[j]); // 此时,j指向pivot的正确位置
 1 class Solution:
 2     def _sortColors(self, nums, l, r):
 3         if l >= r:
 4             return
 5         # pratition
 6         j = l+1
 7         pivot = nums[l]
 8         for i in range(l+1, r+1):
 9             if nums[i] < pivot:
10                 nums[i], nums[j] = nums[j], nums[i]
11                 j += 1
12         j -= 1
13         nums[l], nums[j] = nums[j], nums[l]
14 
15         #devide
16         self._sortColors(nums, l, j-1)
17         self._sortColors(nums, j+1, r)
18     def sortColors(self, nums):
19         """
20         :type nums: List[int]
21         :rtype: void Do not return anything, modify nums in-place instead.
22         """
23         self._sortColors(nums, 0, len(nums)-1)

    这样的一个快排,在面临有序或者近乎有序的数组时,会退化成为一个O(n^2)的算法。于是我们使用了一个很简单的随机选取pivot的方式来处理这个问题。这步随机化让快速排序的时间期望成为了O(nlogn),并且只有极低的概率退化为O(n^2)。
    面对有大量重复元素的数据时,还是有可能退化成O(n^2)级别的。通过这个思路,我们可以进一步优化,提出三路快排的思想。

3.   三路快排

三路快排的Partition代码是这样的。

 1 // v为pivot,初始存储在arr[l]的位置 
 2 int lt = l; // 循环过程中保持 arr[l+1...lt] < v 
 3 int gt = r + 1; // 循环过程中保持 arr[gt...r] > v 
 4 int i = l+1; // 循环过程中保持 arr[lt+1...i) == v 
 5 while( i < gt ){
 6     if( arr[i] < v ){ 
 7         swap( arr[i++], arr[lt+1]); lt ++; } 
 8     else if( arr[i] > v ){ 
 9         swap( arr[i], arr[gt-1]); gt --; } 
10     else // arr[i] == v 
11         i ++; 
12     } 
13 swap( arr[l] , arr[lt] ); 
14 // 此时 arr[lt...gt-1]部分为数组中元素等于v的部分 
15 // 之后只需要递归地对arr[l...lt-1]和arr[gt...r]两部分进行三路快排即可
 1 class Solution:
 2     def _sortColors(self, nums, l, r):
 3         if l >= r:
 4             return
 5         # pratition
 6         pivot = nums[l]
 7         j = l+1  #循环过程中保持 arr[lt+1...j) == v
 8         lt = l #循环过程中保持 arr[l+1...lt] < v
 9         gt = r # 循环过程中保持 arr[gt...r] > v
10         while j <= gt:
11             if nums[j] < pivot:
12                 nums[lt], nums[j] = nums[j], nums[lt]
13                 j += 1
14                 lt += 1
15             elif nums[j] > pivot:
16                 nums[gt], nums[j] = nums[j], nums[gt]
17                 gt -= 1
18             else:
19                 j += 1
20 
21         #devide
22         self._sortColors(nums, l, lt-1)
23         self._sortColors(nums, gt+1, r)
24     def sortColors(self, nums):
25         """
26         :type nums: List[int]
27         :rtype: void Do not return anything, modify nums in-place instead.
28         """
29         self._sortColors(nums, 0, len(nums)-1)

 

posted @ 2018-07-11 00:50  卉卉卉大爷  阅读(627)  评论(0编辑  收藏  举报