[Java 算法] 快速排序和快速选择排序(※)

练习一 : 颜色分类

75. 颜色分类 - 力扣(LeetCode)

java 复制代码
class Solution {
    public void sortColors(int[] nums) {
        int len = nums.length;
        int left = -1;//0元素的最右端
        int right = len;//2元素的最左端
        for(int i = 0;i<right;){
            if(nums[i] == 0){
                swap(nums,++left,i++);
            }else if(nums[i] == 1){
                i++;
            }else{
                swap(nums,--right,i);
            }
        }
    }
    public void swap(int[] nums,int i,int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

算法原理 :

① 指针含义

i : 用来遍历数组

left : 用来标记 0 的最右端 , 包含 left

right : 用来标记 2 的最左端 , 包含 right

② 区间表示

0,left\] 为 0 ; \[left+1,i-1\] 为 1 ; \[i,right-1\] 为待排序元素 ; \[right,len-1\] 为 2 ③ 交换元素 ![](https://i-blog.csdnimg.cn/img_convert/d3c0128d8729e851dd5273172abc2344.png) **如果 i 位置为 0 :** 需要交换 left+1 和 i , 此时如果 i==++left , 是自己根自己交换 ; 交换完成 i++ ; 注意 : 由于 left+1 位置为已经排好序了的元素 , 所以能让 i++ **如果 i 位置为 1** : 仅需要将 i++ **如果 i 位置为 2** : 需要交换 right-1 和 i , 此时如果 i == --right,也是自己自己跟自己交换 , 交换完成退出循环(因为此时 i == right) ## 练习二 : 排序数组(快排) [912. 排序数组 - 力扣(LeetCode)](https://leetcode.cn/problems/sort-an-array/ "912. 排序数组 - 力扣(LeetCode)") ![](https://i-blog.csdnimg.cn/img_convert/dce960886d4e2351180a6c4a451d7ab8.png) ```java class Solution { public int[] sortArray(int[] nums) { qsort(nums,0,nums.length-1); return nums; } public void qsort(int[] nums,int l,int r){ if(l>=r) return ; int key = nums[new Random().nextInt(r-l+1)+l]; int left = l-1, right = r+1; for(int i = l;ikey // 这里 i 不能 key int bigSize = r - right + 1; // 大于key的数量(第k大优先看这里) int midSize = right - left -1; // 等于key的数量 if (bigSize >= k) { // 第k大在右侧大区 return qsort(nums, right, r, k); } else if (bigSize + midSize >= k) { // 第k大就在等于key的区间 return key; } else { // 第k大在左侧小区,更新k值 return qsort(nums, l, left, k - bigSize - midSize); } } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } } ``` ## 练习四 : 库存管理 [LCR 159. 库存管理 III - 力扣(LeetCode)](https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/ "LCR 159. 库存管理 III - 力扣(LeetCode)") ```java class Solution { public int[] inventoryManagement(int[] nums, int k) { // 快速排序划分,将数组前k小的元素放到左侧 qsort(nums, 0, nums.length - 1, k); int[] ret = new int[k]; for(int i = 0; i < k; i++) ret[i] = nums[i]; return ret; } // 快速选择:在 [l, r] 区间划分出最小的 k 个数 public void qsort(int[] nums, int l, int r, int k) { if (l >= r) { // return ; } // 随机选取基准值,避免最坏时间复杂度 int key = nums[new Random().nextInt(r - l + 1) + l]; int left = l - 1; int right = r + 1; // 三路划分:< key | = key | > key // 循环条件必须为 i < right,保证划分正确 for (int i = l; i < right; ) { if (nums[i] < key) { swap(nums, i++, ++left); } else if (nums[i] == key) { i++; } else { swap(nums, i, --right); } } // 划分完成后形成三个区间 // [l, left] 小于 key // [left+1, right-1] 等于 key // [right, r] 大于 key int lessSize = left - l + 1; // 小于基准值的元素个数 int midSize = right - left - 1; // 等于基准值的元素个数 if (k <= lessSize) { // 最小的 k 个数全部在 小于区 中 qsort(nums, l, left, k); } else if (k <= lessSize + midSize) { // 最小的 k 个数包含在 小于区 + 等于区 中,直接结束 return ; } else { // 剩余部分需要在 大于区 中寻找 qsort(nums, right, r, k - lessSize - midSize); } } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } } ```

相关推荐
逻辑驱动的ken1 小时前
Java高频面试考点场景题09
java·开发语言·数据库·算法·oracle·哈希算法·散列表
帅小伙―苏1 小时前
力扣42接雨水
前端·算法·leetcode
AI科技星1 小时前
精细结构常数α的几何本源:从第一性原理的求导证明、量纲分析与全域验证
算法·机器学习·数学建模·数据挖掘·量子计算
6Hzlia1 小时前
【Hot 100 刷题计划】 LeetCode 287. 寻找重复数 | C++ 数组判环 (快慢指针终极解法)
c++·算法·leetcode
MegaDataFlowers1 小时前
26.删除有序数组中的重复项
算法
码完就睡3 小时前
数据结构——栈和队列的相互模拟
数据结构
iiiiyu3 小时前
常用API(SimpleDateFormat类 & Calendar类 & JDK8日期 时间 日期时间 & JDK8日期(时区) )
java·大数据·开发语言·数据结构·编程语言
故事和你913 小时前
洛谷-数据结构1-4-图的基本应用2
开发语言·数据结构·算法·深度优先·动态规划·图论
吴可可1233 小时前
C#合并首尾相连多段线实战
算法·c#
KMDxiaozuanfeng4 小时前
卡梅德生物技术快报|SPR 技术应用|基于 SPR 亲和力的中药活性成分筛选系统实现与数据分析
科技·算法·面试·考试