(總要更好的,等你去發(fā)現(xiàn))
如果對技術(shù)不感興趣的,可以直接跳轉(zhuǎn)到最后的題外話。寫了一點點,支離破碎。也是從這個程序想到的一點點。
今天繼續(xù)和大家聊尋找最大的k個數(shù)。
先來熟悉一下問題:
有很多個無序的數(shù)(我們這里假設(shè)為正整數(shù)),而且各不相等,怎么選出最大的k個數(shù)。
例如:2,5,7,1,3,9,3,6,7,8,5
最大的5個數(shù)為:7,9,6,7,8
昨天我們給出了兩個解法:
快速排序和選擇排序,文章詳情:尋找最大的k個數(shù):快排和選擇(一)
今天我們繼續(xù)。
回想一下快速排序,每次做完一次快速排序,數(shù)組s都會被分成兩部分sa和sb。sb的每一個數(shù)都大于sa的每一個數(shù)。這時候會出現(xiàn)兩種情況:
第一:sb.length >= k,這時候我們只需要關(guān)心sb數(shù)組即可,因為前k個最大的數(shù)都在sb中。
第二:sb.length < k,這時候前k個最大的數(shù)為sb加上sa數(shù)組中前k-sb.length個數(shù)。
下面這段代碼,是在前面快速排序的基礎(chǔ)上修改的。主要是一次快速排序后比較k和
sb數(shù)組的長度。
具體代碼如下:
package com.xylx.utils.selectk;
/
* 優(yōu)化快速排序,查找最大的k個輸
*/
public class optquicksortselectk {
public static void main(string[] args) {
int[] arr = constans.getlengtharr(100);
system.out.println("排序前:");
constans.printarr(arr);
optquicksort(arr, 0, arr.length-1, constans.k);
system.out.println("排序后:");
constans.printarr(arr);
system.out.println("排序是否正確: " constans.isok(arr));
constans.selectk(arr);
}
public static void optquicksort(int[] arr, int start, int end, int k) {
int left = start;
int right = end;
int key = arr[left];
while (left < right) {
while (left<right && arr[right] > key) {
right –;
}
if (left < right) {
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left ;
}
while (left<right && arr[left] < key) {
left ;
}
if (left < right) {
int tmp = arr[right];
arr[right] = arr[left];
arr[left] = tmp;
right–;
}
}
if (start < left-1) {
int rightlength = end – right 1;
system.out.println("rightlength=" rightlength " k=" k);
if (rightlength < k) { //右邊數(shù)組小于需要的k數(shù)
optquicksort(arr, start, left-1, k-rightlength); //需要左邊數(shù)組k-rightlength個最大的數(shù)
}
}
if (right 1 < end) {
int rightlength = end – right 1;
if (rightlength > k) {
optquicksort(arr, right 1, end, k);
}
}
}
}
上面這段代碼能大大降低排序的次數(shù)。
尋找前k個最大數(shù),也就是選擇第k大的數(shù)。
如果數(shù)組s的中最大值為max,最小值為min。那么第k大的值vk一定滿足下面的關(guān)系:
min<=vk<=max。
我們從中間值開始找起,mid=(min max)/2。查找數(shù)組s中所有>=mid的數(shù)的個數(shù)total。這時候也會出現(xiàn)兩種情況:
第一:total>=k, 證明查找出來的數(shù)比k多,我們需要增加mid的值,也就是min=mid。
第二:total<k,證明查找出來的數(shù)比k少,我們需要減少max的值,也就是max=mid。
這樣不斷循環(huán),直到max-min <= 1。
代碼如下:
package com.xylx.utils.selectk;
import java.util.arraylist;
import java.util.list;
/
*/
public class binsearchselectk {
public static void main(string[] args) {
int[] arr = constans.getlengtharr(100);
constans.printarr(arr);
selectk(arr);
}
public static void selectk(int[] arr) {
list<integer> result = getmaxmin(arr);
int max = result.get(0);
int min = result.get(1);
while (max – min > 1) {
int mid = (max min)/2;
int total = getgttotal(arr, mid);
if (total >= constans.k) {
min = mid;
} else {
max = mid;
}
}
system.out.println("min=" min " max=" max);
printk(arr, min);
}
private static void printk(int[] arr, int min) {
int index = 0;
system.out.println("最大的k個數(shù):");
for (int i=0; i<arr.length; i ) {
if (arr[i] > min) {
system.out.print(arr[i] " ");
index ;
}
}
for (int i=0; i<(constans.k-index); i ) {
system.out.print(min " ");
}
}
/
* 查找數(shù)組中大于等于mid值大的數(shù)的個數(shù)
* @param arr
* @param mid
* @return
*/
public static int getgttotal(int[] arr, int mid) {
int total = 0;
for (int i=0; i<arr.length; i ) {
if (arr[i] >= mid) {
total ;
}
}
return total;
}
/
* 尋找數(shù)組中最大值和最小值
* @param arr
* @return 0:最大 1:最小
*/
public static list<integer> getmaxmin(int[] arr) {
list<integer> result = new arraylist<integer>();
if (arr == null || arr.length < 1) {
return result;
}
int max = integer.min_value;
int min = integer.max_value;
for (int i=0; i<arr.length; i ) {
if (a
中國生活O2O十五年沉浮錄備案申請退回咨詢-備案平臺新人對于域名注冊商該怎么去選擇?阿里云服務(wù)器必須進行備案嗎3大主流視頻平臺的VIP會員成長體系!騰訊云服務(wù)器鏡像還原怒江云服務(wù)器租用購買阿里云怎么購買高防服務(wù)器