无序数组中最小的k个数
对于一个无序数组,数组中元素为互不相同的整数,请返回其中最小的k个数。
给定一个整数数组A及它的大小n,同时给定k,请返回其中最小的k个数。
[1,2,4,3],4,2
返回:[1,2]
(1)利用堆,时间复杂度O(Nlogk)
public class Main {
public static void main(String[] args) {
Main test = new Main();
int[] a={3188,4522,2526,4085,1621,723,1073};
int[] b=new int[6];
b=test.findKthNumbers(a,7,6);
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
System.out.println(b[4]);
System.out.println(b[5]);
}
public int[] findKthNumbers(int[] A, int n, int k) {
if(A==null||n<=k||k<1){
return A;
}
int[] result=new int[k];
heapSort(A,result,k);
for(int i=k;i<n;i++){
if(A[i]<result[0]){
heapModify(result,A[i]);
}
}
return result;
}
public void heapSort(int[] arr,int[] result,int k){
result[0]=arr[0];
for(int i=0;i<k;i++){
result[i]=arr[i];
int index=i;
int parent=(i-1)/2;
while(parent>=0&&result[parent]<result[index]){
swap(result,parent,index);
index=parent;
parent=(parent-1)/2;
}
}
}
public void heapModify(int[] arr,int key){
arr[0]=key;
int k=arr.length;
int index=0;
int child=(index+1)*2-1;
if(child+1<k){
child=arr[child]>=arr[child+1]?child:child+1;
}
while(child<k&&arr[index]<arr[child]){
swap(arr,index,child);
index=child;
child=(child+1)*2-1;
if(child+1<k){
child=arr[child]>=arr[child+1]?child:child+1;
}
}
}
public void swap(int[] arr,int i,int j){
int temp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
(2) 利用快排 平均O(n) 最坏O(n^2)
public class Main {
public static void main(String[] args) {
Main test = new Main();
int[] a={3188,4522,2526,4085,1621,723,1073};
int[] b=new int[6];
b=test.findKthNumbers(a,7,6);
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
System.out.println(b[4]);
System.out.println(b[5]);
}
public int[] findKthNumbers(int[] input, int n, int k) {
if(input==null||n<=k||k<1){
return input;
}
int[] result=new int[k];
int start=0,end=input.length-1,key,i,j;
while(end!=k-1){
key=input[start];
i=start;
j=end;
while(i<j){
while(i<j&&input[j]>=key){
j--;
}
input[i]=input[j];
while(i<j&&input[i]<=key){
i++;
}
input[j]=input[i];
}
input[i]=key;
if(i==k-1) break;
if(i>k-1)end=i-1;
else start=i+1;
}
for(i=0;i<k;i++){
result[i]=input[i];
}
return result;
}
}
(3)bfprt 时间复杂度O(n)
public class Main {
public static void main(String[] args) {
Main test = new Main();
int[] a={3188,4522,2526,4085,1621,723,1073};
int[] b=new int[6];
b=test.findKthNumbers(a,7,6);
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
System.out.println(b[4]);
System.out.println(b[5]);
}
public int[] findKthNumbers(int[] A, int n, int k) {
if(A==null||n<=k||k<1){
return A;
}
int[] result=new int[k];
int key;
int j=0;
key=findK(A,0,n-1,k);//找到第k小数的值;
for(int i=0;i<n;i++){
if(A[i]<key){
result[j++]=A[i];
}
}
while(j!=k){
result[j++]=key;
}
return result;
}
public int findK(int[] arr,int start,int end,int k){
int key;
int[] index=new int[2];
key=selectKey(arr,start,end);//找中位数。
index=quickSort(arr,start,end,key);//以中位数为基准,快速排序。
if(index[0]<=k-1&&k-1<=index[1]){
return arr[index[0]];
}
else if(index[0]>k-1){
return findK(arr,0,index[0],k);
}
else{
return findK(arr,index[1]+1,end,k);
}
}
//使用bfprt算法寻找中位数
public int selectKey(int[] arr,int start,int end){
if(end-start<=4){
return midKey(arr,start,end);
}
int[] temp=new int[(end-start)/5+1];
int j=0;
for(int i=start;i<=end;i+=5){
temp[j++]=midKey(arr,i,Math.min(end,i+4));
}
return selectKey(temp,0,(end-start)/5);
}
//按中位数值快速排序
public int[] quickSort(int[] arr,int start,int end,int key){
int[] index=new int[2];
if(start==end){
index[0]=index[1]=start;
return index;
}
int cur=start;
int left=start;
int right=end;
while(cur<=right){
if(arr[cur]>key){
swap(arr,cur,right--);
}
else if(arr[cur]<key){
swap(arr,cur++,left++);
}
else{
cur++;
}
}
index[0]=left;
index[1]=right;
return index;
}
//对没五个的小组进行插入排序并返回小组中位数。
public int midKey(int[] arr,int start,int end){
if(start==end){
return arr[start];
}
int mid=(start+end)/2;
for(int i=start+1;i<=end;i++){
int key=arr[i];
int j=i-1;
while(j>=start&&key<arr[j]){
arr[j+1]=arr[j--];
}
arr[++j]=key;
}
return arr[mid];
}
public void swap(int[] arr,int i,int j){
int temp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
无序数组中最小的k个数
对于一个无序数组,数组中元素为互不相同的整数,请返回其中最小的k个数,顺序与原数组中元素顺序一致。
给定一个整数数组A及它的大小n,同时给定k,请返回其中最小的k个数。
[1,2,4,3],4,2
返回:[1,2]
(1)堆实现:
public int[] findKthNumbers(int[] A, int n, int k) {
if(A==null||n<=k||k<1){
return A;
}
int[] result=new int[k];
heapSort(A,result,k);
for(int i=k;i<n;i++){
if(A[i]<result[0]){
heapModify(result,A[i]);
}
}
int j=0;
int count=0;
int key=result[0];
for(int i=0;i<n;i++){
if(A[i]<key){
count++;
}
}
int c=k-count;
for(int i=0;i<n;i++){
if(A[i]<key){
result[j++]=A[i];
}
if(A[i]==key&&c-->0){
result[j++]=A[i];
}
}
return result;
}
public void heapSort(int[] arr,int[] result,int k){
result[0]=arr[0];
for(int i=0;i<k;i++){
result[i]=arr[i];
int index=i;
int parent=(i-1)/2;
while(parent>=0&&result[parent]<result[index]){
swap(result,parent,index);
index=parent;
parent=(parent-1)/2;
}
}
}
public void heapModify(int[] arr,int key){
arr[0]=key;
int k=arr.length;
int index=0;
int child=(index+1)*2-1;
if(child+1<k){
child=arr[child]>=arr[child+1]?child:child+1;
}
while(child<k&&arr[index]<arr[child]){
swap(arr,index,child);
index=child;
child=(child+1)*2-1;
if(child+1<k){
child=arr[child]>=arr[child+1]?child:child+1;
}
}
}
public void swap(int[] arr,int i,int j){
int temp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
(2)bfprt
public int[] findKthNumbers(int[] A, int n, int k) {
if(A==null||n<=k||k<1){
return A;
}
int[] result=new int[k];
int key;
int j=0;
int[] copyArr=new int[n];
for (int i = 0; i < n; i++) {
copyArr[i] = A[i];
}
key=findK(copyArr,0,n-1,k);//找到第k小数的值;
int count=0;
for(int i=0;i<n;i++){
if(A[i]<key){
count++;
}
}
int c=k-count;
for(int i=0;i<n;i++){
if(A[i]<key){
result[j++]=A[i];
}
if(A[i]==key&&c-->0){
result[j++]=A[i];
}
}
return result;
}
public int findK(int[] arr,int start,int end,int k){
int key;
int[] index=new int[2];
key=selectKey(arr,start,end);//找中位数。
index=quickSort(arr,start,end,key);//以中位数为基准,快速排序。
if(index[0]<=k-1&&k-1<=index[1]){
return arr[index[0]];
}
else if(index[0]>k-1){
return findK(arr,0,index[0],k);
}
else{
return findK(arr,index[1]+1,end,k);
}
}
//使用bfprt算法寻找中位数
public int selectKey(int[] arr,int start,int end){
if(end-start<=4){
return midKey(arr,start,end);
}
int[] temp=new int[(end-start)/5+1];
int j=0;
for(int i=start;i<=end;i+=5){
temp[j++]=midKey(arr,i,Math.min(end,i+4));
}
return selectKey(temp,0,(end-start)/5);
}
//按中位数值快速排序
public int[] quickSort(int[] arr,int start,int end,int key){
int[] index=new int[2];
if(start==end){
index[0]=index[1]=start;
return index;
}
int cur=start;
int left=start;
int right=end;
while(cur<=right){
if(arr[cur]>key){
swap(arr,cur,right--);
}
else if(arr[cur]<key){
swap(arr,cur++,left++);
}
else{
cur++;
}
}
index[0]=left;
index[1]=right;
return index;
}
//对没五个的小组进行插入排序并返回小组中位数。
public int midKey(int[] arr,int start,int end){
if(start==end){
return arr[start];
}
int mid=(start+end)/2;
for(int i=start+1;i<=end;i++){
int key=arr[i];
int j=i-1;
while(j>=start&&key<arr[j]){
arr[j+1]=arr[j--];
}
arr[++j]=key;
}
return arr[mid];
}
public void swap(int[] arr,int i,int j){
int temp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}