快速排序总结

快速排序

1. 写在之前

快速排序还有不会的?

虽然快速排序的想法深入各个程序员的心中,但在面试高压情况下,想要一次流畅正确地写出快排或者用到快排的题目并非容易的事情,经常会出现一些这样那样的小bug,给面试官留下不好的映象。

本文将解决:

  • 快速排序的一般框架
  • 两种划分方法以及可能出错的点
  • 循环不变量验证

2. 快排框架

快速排序的框架非常简单,与归并排序一样,是分治法的体现,思路为:

假设为升序排序,快排将数组划分为两个部分,左边的部分小于某数,后边的部分大于某数,然后在再对数组的左右两部分各自再进行排序。

class Solution{
	public int[] sort(int[] nums){
		sort(nums, 0. nums.length - 1); // 1
		return nums;
	}
	public void sort(int[] nums, int start, int end){
		if(start >= end){
			return;  // 2
		}
		int mid = partition(nums, start, end);
		sort(nums, start, mid-1); //3
		sort(nums, mid+1, end);   //3
	}
}

框架中的易错点。

  1. 这里为了划分方便,用的是左右闭区间(也可以使用开区间,但划分步骤得修改)。
  2. 递归的终止条件,若无就会导致栈溢出
  3. 新的排序应该去掉返回的mid值,增加效率

3. Partition

划分是快速排序的重头戏,也是bug的高发区域,容易出错的地方是:

  • 划分的方法
  • 划分的左右边界,的初始值设置和结束条件
  • 划分的返回值
3.1 双指针法

双指针法,顾名思义就是左右两个指针,

  • 首先选择第一个为标的,
  • 左指针指向第一个比标的大的数,右指针指向第一个比标的小的数,然后交换左右指针;
  • 不断重复,直到左指针大于右指针;
  • 将右指针和第一个位置替换。
 private int partition(int[] nums, int start, int end){
     int left = start + 1;
     int right = end;
     int target = nums[start];
     while(left <= right){
         // search left
         while(left <= right && nums[left] <= target ){ //1
             left++;
         }
         while(left <= right &&nums[right] > target){
             right--;
         }
         if(left<=right){
             swap(nums, left, right);
         }
         // search right
     }
     swap(nums, start, right);
     return right;
 }

易错的地方:

  1. 终止条件,

这里选择的是当left不大于right的时候,说明最后跳出循环的时候是left > right,且大于1;

可以推导出一个结论,right最终指向部分肯定有nums[right] >= target,所以跳出循环后用right交换start,而不是left。(留作思考,关注语句1最后两句的执行情况)

3.2 三指针法

三指针法相较于双指针法,多了一个遍历指针,此时左右指针的含义有所不同。

指针开始结束
左指针指向第一个仅可能大于等于target数,左端指向第一个等于target的数,其左边都会小于target
右指针指向第一个小于等于target的数,右端指向最后一个等于target的数,其右边会大于target
遍历指针左端+1最终右指针+1
private int partition(int[] nums, int start, int end){
	int left = start;
	int right = end;
	int i = left + 1;
	int target = nums[start];
	while(i <= right){
		if(nums[i] < target){
			// nums[i]小于target, 应该在左侧,与左侧交换, 两个指针都增长,因为i指针遍历过的位置,都表示左边已经
			swap(nums, i, left);
			left++;
			i++;
		}
		else if(nums[i] > target){
			swap(nums, i, right);
			right--;
		}
		else{
			i++;
		}
	}
	return right;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值