循环结束后交换基准元素和 storeIndex 位置的元素的位置:
pivot
↓
3 4 2 1 5 5 9 8 7
↑
storeIndex
那么 storeIndex 的值就是基准元素的最终位置,这样整个分区过程就完成了。
下面我们来看一下源码是怎样实现的
1. 简单来说就是先找出一个索引,左边的数都比他小,右边的数都比他大 ,接着利用递归排列左边和右边的数,直到low>=high
private static void qSort(int[] data, int low, int high) {
int pivot;
if (low < high) {
pivot = partition(data, low, high);
qSort(data, 0, pivot - 1);
qSort(data, pivot + 1, high);
}
}
2. 下面我们来看一下partition函数式怎样实现的
private static int partition(int[] data, int low, int high) {
int pivotKey;
pivotKey = data[low];
while (low < high) {
// 将小于基准点的值得数放到前面
while (low < high && data[high] >= pivotKey) {//
high–;
}
ArrayUtils.exchangeElements(data, low, high);
// 将大于基准点的值得数放到后面
while (low < high && data[low] <= pivotKey) {
low++;
}
ArrayUtils.exchangeElements(data, low, high);
}
// 返回基准点的索引
return low;
}
其实就是从两端进行扫描,发现小于基准点的 数的时候,将其放到前面到,发现大于基准点的数的时候,将其发到后面去
到此快速排序的分析为止
数组中出现次数超过一半的数字
一、问题描述
给定一个数组,数组中的数据无序,在一个数组中找出其第k个最小的数,例如对于数组x,x = {3,2,1,4,5,6},则其第2个最小的数为2。
二、解题思路
本算法跟快排的思想相似,首先在数组中选取一个数centre作为枢纽,将比centre小的数,放到centre的前面将比centre大的数,放到centre的后面。如果此时centre的位置刚好为k,则centre为第k个最小的数;如果此时centre的位置比k前,则第k个最小数一定在centre后面,递归地在其右边寻找;如果此时centre的位置比k后,则第k个最小数一定在centre后面,递归地在其左边寻找。
三、代码
package com.xujun.quicksort;
import java.util.Collections;
public class MinIndex {
static int[] a = new int[] { 20, 9, 3, 5, 26, 100, 8, -1, 7, 50, -5, 20, -1 };
public static void main(String[] args) {
System.out.println(“before sort”);
ArrayUtils.printArray(a);
int k=8;
int pivot = findMinIndexInArray(a, k);
System.out.println(“after sort”);
ArrayUtils.printArray(a);
System.out.println(“数组中最小的第”+k+"个数是 " + a[pivot]);
}
private static int findMinIndexInArray(int[] data, int k) {
if (data == null || data.length < k) {
return -1;
}
int start = 0;
int end = data.length - 1;
int pivot = partition(data, start, end);
while (pivot != k - 1) {
if (pivot < k - 1) {
start = pivot + 1;
pivot = partition(data, start, end);
} else {
end = pivot - 1;
pivot = partition(data, start, end);
}
}
return pivot;
}
private static int partition(int[] data, int low, int high) {
int pivotKey;
/*
- pivotKey = data[low];// 选取low作为基准点,pivotKey为基准点的值
*/
int middle = low + (high - low) / 2;
if (data[low] > data[high]) {// 较大的数存在high中
ArrayUtils.exchangeElements(data, low, high);
}
if (data[middle] > data[high]) {
ArrayUtils.exchangeElements(data, middle, high);
}
if (data[middle] > data[low]) {
ArrayUtils.exchangeElements(data, middle, low);
}
pivotKey = data[low];// 选取low作为基准点,pivotKey为基准点的值
// 将大于基准点的值得数放到后面
while (low < high) {
while (low < high && data[high] >= pivotKey) {//
high–;
}
data[low] = data[high];
// 将小于基准点的值得数放到前面
while (low < high && data[low] <= pivotKey) {
low++;
}
data[high] = data[low];
}
data[low] = pivotKey;
// 返回基准点的索引
return low;
}
}
2 数组中最小的第k个数
一、问题描述
给定一个数组,找出数组中元素出现次数超过数组长度一半的元素
如数组:
[4, 3, 2, 1, 1, 1, 1, 1, 1, 0 ]
其中超过一半的元素就是 1
二、解题思路
1)本题同样可以医用快速排序的思想来做,如果一个数字出现次数超过一般,那么排好序的数组的中间数肯定就是出现次数超过一半的数字
2)考虑异常情况下,出现次数没有超过一半
遍历数组,检查一下
三、代码
package com.xujun.quicksort;
import java.util.Collections;
public class MoreThanHalf {
static int[] a = new int[] { 20, 9, 3, 5, 10,10,10,10,10 };
public static void main(String[] args) {
System.out.println(“before sort”);
ArrayUtils.printArray(a);
int k = 8;
int pivot = findMoreHalfInArray(a);
int target = a[pivot];
boolean checkIsMoreThanHalf = checkIsMoreThanHalf(a, target);
if(checkIsMoreThanHalf){
System.out.println(“after sort”);
ArrayUtils.printArray(a);
System.out.println(“超过一般的数是=”+target);
}else{
System.out.println(“没有超过一般的数字”);
}
}
private static boolean checkIsMoreThanHalf(int[] data, int target) {
int half=data.length/2;
int count=0;
for(int i=0;i<data.length;i++){
if(data[i]==target){
count++;
}
}
return count>=half?true:false;
}
private static int findMoreHalfInArray(int[] data) {
if (data == null || data.length <= 0) {
return -1;
}
int start = 0;
int end = data.length - 1;
int half = data.length / 2;
int pivot = partition(data, start, end);
while (pivot != half - 1) {
if (pivot < half - 1) {// 枢轴在一半的 左边
start = pivot + 1;
pivot = partition(data, start, end);
} else {// 枢轴在一半(中间点)的右边
end = half - 1;
pivot = partition(data, start, end);
}
}
return pivot;
}
private static int partition(int[] data, int low, int high) {
int pivotKey;
/*
- pivotKey = data[low];// 选取low作为基准点,pivotKey为基准点的值
*/
int middle = low + (high - low) / 2;
if (data[low] > data[high]) {// 较大的数存在high中
ArrayUtils.exchangeElements(data, low, high);
}
if (data[middle] > data[high]) {
ArrayUtils.exchangeElements(data, middle, high);
}
if (data[middle] > data[low]) {
ArrayUtils.exchangeElements(data, middle, low);
}
pivotKey = data[low];// 选取low作为基准点,pivotKey为基准点的值
// 将大于基准点的值得数放到后面
while (low < high) {
while (low < high && data[high] >= pivotKey) {//
high–;
}
data[low] = data[high];
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。
下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。
不论遇到什么困难,都不应该成为我们放弃的理由!
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
内容对你有帮助,可以扫码获取!!(备注:Android)**
最后
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
同时我经过多年的收藏目前也算收集到了一套完整的学习资料以及高清详细的Android架构进阶学习导图及笔记分享给大家,希望对想成为架构师的朋友有一定的参考和帮助。
下面是部分资料截图,诚意满满:特别适合有开发经验的Android程序员们学习。
[外链图片转存中…(img-toAbpaPJ-1711964677081)]
不论遇到什么困难,都不应该成为我们放弃的理由!
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。