最近这一两天,终于有空复习以前学习的东西了。前面忙着学SpringCloud和Netty感觉花费了太多时间,做项目也是。后来实习的面试准备就等于没准备,全靠着以前学习的记忆面试。果不其然,效果不是很好。
这里建议大家做项目量力而行,最好还是多学习和复习所学的知识。毕竟别人往往一两句话就认定了你的项目的水准和花费的努力。而复习所学的知识,反而才更适合现在的环境。
吐槽完毕,最近终于有时间做题了,重新复习了下快排。(毕竟用了很多次,所以写一写,当作复习了)
下面是java版本的快速排序、快速选择。
public Test{
@Test
public void testSort() {
// 选择前11小的数字
int[] arr1 = {10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1};
quickTopN(arr1, true, 0, arr1.length - 1, 10);
System.out.println("选择前11小的数字");
for (int item : arr1) {
System.out.printf("%d ", item);
}
System.out.println();
// 选择前11大的数字
int[] arr2 = {1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,10};
quickTopN(arr2, false, 0, arr2.length - 1, 10);
System.out.println("选择前11大的数字");
for (int item : arr2) {
System.out.printf("%d ", item);
}
System.out.println();
// 快排,升序
int[] arr3 = {1,9,3,4,7,6,2,4,8,1,5,2,6,5,2,4,7,5,1,3,6,9,5,1,3,4,7,1,2,8,3,5,8,2,4,2,1,5,7,6,2,1,4,6,9,2,4,7,1,3,5,8,1,2,6,6,2,1,7,1,2,6,4,8,1,3,5,7,1,2};
quickSort(arr3, true, 0,arr3.length-1);
System.out.println("快排,升序");
for (int item : arr3) {
System.out.printf("%d ", item);
}
System.out.println();
// 快排,降序
int[] arr4 = {4,5,7,1,3,5,2,1,9,3,4,1,2,5,8,71,2,1,5,4,1,3,9,5,1,2,5,4,7,2,3,3,1,5,4,8,6,2,4,7,1,6,1,2,5,4,3,9,2,4,2,2,7,6,1,36,5,4,8,2,1,3,5,7,1,54,2,2,81,3,5,7,21,6,5,2,78,2,4,5,9};
quickSort(arr4, false, 0,arr4.length-1);
System.out.println("快排,降序");
for (int item : arr4) {
System.out.printf("%d ", item);
}
System.out.println();
}
/**
* TopN,快速选择(类快排)
*
* @param rawArr 原始数组
* @param isAsc 是否升序,false则降序
* @param start 需要筛选的闭区间的左边界
* @param end 需要筛选的闭区间的右边界
* @param targetEnd 需要得到的有序的闭区间的右边界
* @apiNote 例如 rawArr=[1,6,4,2,3,5] isAsc=false, start=0 end=5, targetEnd=3,
* 表示需要 得到长度6的数组rawArr的前4大的数字(0,1,2,3下标是4个数字)
*/
public int[] quickTopN(int[] rawArr, boolean isAsc, int start, int end, int targetEnd) {
int basePos = quickSelect(rawArr, isAsc, start, end);
if (basePos == targetEnd) return rawArr;
return basePos >= targetEnd ? quickTopN(rawArr, isAsc, start, basePos - 1, targetEnd) : quickTopN(rawArr, isAsc, basePos + 1, end, targetEnd);
}
/**
* 快速排序
* @param rawArr 需要快排的原始数组
* @param isAsc 是否升序
* @param start 需要快排的闭区间的左边界
* @param end 需要快排的闭区间的右边界
*/
public void quickSort(int[] rawArr, boolean isAsc,int start,int end) {
int mid = quickSelect(rawArr, isAsc, start, end);
if(start<mid)
quickSort(rawArr,isAsc,start, mid-1);
if(mid<end)
quickSort(rawArr,isAsc,mid+1, end);
}
/**
* 快速选择
* @param rawArr 需要快速选择的原数组
* @param isAsc 是否升序
* @param start 需要快速选择的闭区间的左边界
* @param end 需要快速选择的闭区间的右边界
* @return 返回基准的下标
*/
public int quickSelect(int[] rawArr, boolean isAsc, int start, int end) {
int baseVal = rawArr[start];
int left = start, right = end;
while (left < right) {
if (isAsc) {
while (left < right && rawArr[right] >= baseVal)
--right;
while (left < right && rawArr[left] <= baseVal)
++left;
} else {
while (left < right && rawArr[right] <= baseVal)
--right;
while (left < right && rawArr[left] >= baseVal)
++left;
}
if(left<right){
int tmp = rawArr[left];
rawArr[left] = rawArr[right];
rawArr[right] = tmp;
}
}
rawArr[start] = rawArr[left];
rawArr[left] = baseVal;
return left;
}
}
输出结果如下(最好自己复制代码试试)
选择前11小的数字
1 1 1 2 2 2 3 3 3 4 4 7 6 6 6 5 5 5 4 7 7 8 8 8 9 9 9 10 10 10
选择前11大的数字
10 10 10 9 9 9 8 8 8 7 7 4 5 5 5 6 6 6 7 4 4 3 3 3 2 2 2 1 1 1
快排,升序
1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 8 8 8 8 8 9 9 9
快排,降序
81 78 71 54 36 21 9 9 9 9 8 8 8 7 7 7 7 7 7 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1