排序思想-快排

快速排序

912.排序数组 

快速排序核心思想就是每次在当前区间 [left, right] 中选择出一个元素 nums[p],然后将区间内所有大于它的元素和所有小于它的元素都放到其两侧【具体放在哪一侧取决于是升序还是降序】,然后再递归去处理两侧区间。

class Solution {
    public int[] sortArray(int[] nums) {
        quickSort2(nums,0,nums.length-1);
        return nums;
    }
    // 荷兰国旗问题
	public static int first, last;
    public static void quickSort2(int[] arr, int l, int r) {
		if(l>=r) return;
		// 随机这一下,常数时间比较大
		// 但只有这一下随机,才能在概率上把快速排序的时间复杂度收敛到O(n * logn)
		int x = arr[l + (int) (Math.random() * (r - l + 1))];
		partition2(arr, l, r, x);
		// 为了防止底层的递归过程覆盖全局变量
		// 这里用临时变量记录first、last
		int left = first;
		int right = last;
		quickSort2(arr, l, left - 1);
		quickSort2(arr, right + 1, r);
	}

	// 已知arr[l....r]范围上一定有x这个值
	// 划分数组 <x放左边,==x放中间,>x放右边
	// 把全局变量first, last,更新成==x区域的左右边界
	public static void partition2(int[] arr, int l, int r, int x) {
		first = l;
		last = r;
		int i = l;
		while (i <= last) {
			if (arr[i] == x) {
				i++;
			} else if (arr[i] < x) {
				swap(arr, first++, i++);
			} else {
				swap(arr, i, last--);
			}
		}
	}
    public static void swap(int[] nums, int i, int j){
        if(i==j) return;
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
    
}

双指针交换的方式划分左右区间

215.数组中第K个最大元素.

将大于切分值的元素都放到左侧,小于切分值得元素都放到右侧。因此我们可以使用双指针分别从两端往中间搜索,分别找到左侧小于切分值的元素和右侧大于切分值的元素,交换之,直到两个指针相遇。

对于这道题,我们可以选择区间的中间值作为切分元素,并且我们要事先将切分值交换到区间的右边界:

  1. 避免在划分左右区间的时候,将切分值给覆盖掉。
  2. 最终才可以将切分值放到正确的位置。
class Solution {
    public int findKthLargest(int[] nums, int k) {
        return quickSortKth(nums,k,0,nums.length-1);
    }
    private int quickSortKth(int[] nums, int k, int left, int right){
        int mid =left + (right-left) / 2; 
        swap(nums,mid, right);  // 将切分值放到右边界避免加入元素的划分
        int partition = nums[right], i=left, j=right;  // 双指针从左右边界开始,分别找到要交换的元素
        while(i<j){
            while(i<j && nums[i]>=partition) i++;
            while(j>i && nums[j]<=partition) j--;  // 找到右侧大于切分值的元素【因为是找大于,即使j从right开始,right也不会被选中】
            swap(nums,i,j);
        }
        swap(nums,i,right); // i最后停留的位置一定是右侧首个小于切分值的元素,与切分值交换,则[left, i)都是大于(等于)切分值,[i+1, right]都是小于(等于)切分值

        if(i==k-1) return nums[i];
        if(i<k-1) return quickSortKth(nums,k,i+1,right);
        return quickSortKth(nums,k,left,i-1);

    }
    private void swap(int[] nums, int i, int j){
        if(i == j) return;
        nums[i] ^= nums[j];
        nums[j] ^= nums[i];
        nums[i] ^= nums[j];
    }
}

 

相关推荐

  1. 排序思想-

    2024-07-18 16:16:05       25 阅读
  2. 排序算法】之

    2024-07-18 16:16:05       58 阅读
  3. 排序 - (quick sort)

    2024-07-18 16:16:05       57 阅读
  4. 经典面试排序题(

    2024-07-18 16:16:05       30 阅读
  5. 常见排序算法,,希尔,归并,堆

    2024-07-18 16:16:05       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 16:16:05       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 16:16:05       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 16:16:05       57 阅读
  4. Python语言-面向对象

    2024-07-18 16:16:05       68 阅读

热门阅读

  1. pytorch学习(一)argparse

    2024-07-18 16:16:05       24 阅读
  2. logback-spring.xml配置

    2024-07-18 16:16:05       17 阅读
  3. 嵌入式Linux应用开发基础-现有动态库so的使用

    2024-07-18 16:16:05       21 阅读
  4. Git常用命令详解

    2024-07-18 16:16:05       22 阅读
  5. git 指令速查

    2024-07-18 16:16:05       18 阅读
  6. IO多路复用技术、select、poll、epoll联系与区别

    2024-07-18 16:16:05       27 阅读
  7. C语言实现内存管理

    2024-07-18 16:16:05       17 阅读
  8. 行列视(RCV)支持哪些类型的数据源?

    2024-07-18 16:16:05       20 阅读
  9. C++——模板的奥秘

    2024-07-18 16:16:05       22 阅读
  10. WINUI——实现点在直线上随意移动

    2024-07-18 16:16:05       23 阅读
  11. 关于pip Install与conda install

    2024-07-18 16:16:05       23 阅读
  12. 梯度被原地修改,破坏了计算图

    2024-07-18 16:16:05       26 阅读
  13. matlab实现建立一个学生成绩管理系统

    2024-07-18 16:16:05       22 阅读