[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; } } ```

相关推荐
人间打气筒(Ada)2 小时前
「码动四季·开源同行」golang:负载均衡如何提高系统可用性?
算法·golang·开源·go·负载均衡·负载均衡算法
司马万2 小时前
RUST基础1----数据类型
开发语言·算法·rust
卷福同学2 小时前
Claude Code源码泄露:8大隐藏功能曝光
人工智能·后端·算法
阿豪学编程11 小时前
LeetCode724.:寻找数组的中心下标
算法·leetcode
墨韵流芳11 小时前
CCF-CSP第41次认证第三题——进程通信
c++·人工智能·算法·机器学习·csp·ccf
csdn_aspnet12 小时前
C# 求n边凸多边形的对角线数量(Find number of diagonals in n sided convex polygon)
开发语言·算法·c#
凌波粒12 小时前
LeetCode--349.两个数组的交集(哈希表)
java·算法·leetcode·散列表
paeamecium14 小时前
【PAT甲级真题】- Student List for Course (25)
数据结构·c++·算法·list·pat考试
Book思议-14 小时前
【数据结构】栈与队列全方位对比 + C 语言完整实现
c语言·数据结构·算法··队列