赞
踩
欢迎关注公众号K的笔记阅读博主更多优质学习内容
快速排序是我们在面试时常常遇到的算法,我们接下来首先介绍快速排序的基本思想,然后手撸一遍快速排序算法,最后我们介绍一些特殊情景的应用。
快速排序算法是冒泡排序算法的一种改进,其主要思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据比另一部分所有数据小,整个过程可以递归进行,最终使整个数据变成有序序列。但快速排序是一种不稳定的排序算法,即相同元素不能保序,因此在一些实际场景中不能进行使用。
下图是 Partition 操作的主要方式,下面分别介绍两种方法 —— 挖坑法和指针交换法。
首先我们的数组元素排序如下:
首先我们选定基准元素Pivot,并记住这个位置index,这个位置相当于一个“坑”,并且设置两个指针 left 和 right ,指向数列的最左和最右两个元素。
接下来,从right指针开始,把指针所指向的元素和基准元素做比较。如果比pivot大,则right指针向左移动;如果比pivot小,则把right所指向的元素填入坑中。两个指针接触时算法停止。
4>2,所以4的位置不变,将right指针左移继续比较,right右边黄色的区域代表着大于基准元素的区域。
1<2,所以把1填入基准元素所在位置,也就是坑的位置。这时候,元素1本来所在的位置成为了新的坑。同时,left向右移动一位。
此时,left左边绿色的区域代表着小于基准元素的区域,接下来,我们切换到left指针进行比较。如果left指向的元素小于pivot,则left指针向右移动;如果元素大于pivot,则把left指向的元素填入坑中。
下面是挖坑法另一个例子,来自这篇博客
指针交换法的思想是同时遍历左右边,交换不满足条件的两个元素,下面的例子同样来自这篇博客:
由于上面的图片讲的已经很清楚了,这里就不再进行讲解,下面直接上代码。
下面提供一个最简单的实现,想要寻求刺激的可以直接看下一节。
import random
def quickSort(arr):
if len(arr) < 2:
return arr
pivot = arr[random.randint(0,9)]
left, right = [], []
arr.remove(pivot)
for item in arr:
if item >= pivot:
right.append(item)
else:
left.append(item)
return quickSort(left) + pivot + quickSort(right)
我们首先看到 leetcode 的215题:
这个题我们可以用快速排序的思维来解题。我们在进行快速排序时,每进行一次 Partition,我们就能知道该基准元素的最终位置,因此我们只需要找到排名第二的元素即可,我们来看一下这个题的代码:
class Solution(object): def findKthLargest(self, nums, k): """ :type nums: List[int] :type k: int :rtype: int """ self._k = len(nums) - k return self.quickSort(nums, 0, len(nums)-1) def quickSort(self, nums, left, right): if left == right: return nums[left] pivot = self.partition(nums, left, right) if pivot == self._k: return nums[pivot] elif pivot < self._k: return self.quickSort(nums, pivot+1, right) else: return self.quickSort(nums, left, pivot-1) def partition(self, nums, left, right): pivot = nums[left] i, j = left, right while i < j: while i < j and nums[j] >= pivot: j -= 1 if i < j: nums[i] = nums[j] i += 1 while i < j and nums[i] <= pivot: i += 1 if i < j: nums[j] = nums[i] j -= 1 nums[i] = pivot return i
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。