思路1:最小堆,时间复杂度O(nlogm)
分析:
1、建一个大小为m的最小堆,最小的元素在根部
2、遍历序列,若元素大于根部元素,则用该元素替换根部元素,并对最小堆进行调整,若元素小于等于根部元素,则不对最小堆做任何改变,这样遍历完整个序列后堆中的元素就是最大的m个元素
public class T1
{
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
while(in.hasNext())
{
int n=in.nextInt();
int m=in.nextInt();
int[] arr=new int[n];
for(int i=0;i<n;i++)
{
arr[i]=in.nextInt();
}
solve(arr, m);
}
}
static void minHeap(int[] arr,int len,boolean isOnlyRoot)
{
int s=isOnlyRoot?0:len/2-1;
int d=0;
for(int i=s;i>=d;i--)
{
int k=i;
for(int j=2*k+1;j<len;k=j,j=2*k+1)
{
if(j+1<len && arr[j+1]<arr[j])
{
j=j+1;
}
if(arr[k]>arr[j])
{
swap(arr, k, j);
}
else
{
break;
}
}
}
}
static void solve(int[] arr,int m)
{
minHeap(arr, m, false);
for(int i=m;i<arr.length;i++)
{
if(arr[i]>arr[0])
{
arr[0]=arr[i];
minHeap(arr, m, true);
}
}
for(int i=0;i<m;i++)
{
System.out.println(arr[i]+" ");
}
}
static void swap(int[] arr,int i,int j)
{
arr[i]=arr[i]+arr[j];
arr[j]=arr[i]-arr[j];
arr[i]=arr[i]-arr[j];
}
}
思路2:快排,时间复杂度O(n)
分析:
假如能找到第m大的元素,并且将比该元素大的放在左边,比该元素小的放在右边,那么问题也就解决了。通过快排可以做这一点。如何做呢?
1:得到索引i,比a[i]的在其左边,比a[i]小的在其右边。根据i的值分别执行以下操作。
2:若i>m,则说明第m大的元素在a[i]左边,此时需要从i左边的元素中找出第m大的元素,即对i左边区域进行步骤1
3、若i﹤m-1,则说明第m大的元素在a[i]右边,此时需要从i的右边的元素中找出第m大的元素,即对i右边的原色进行步骤1
4、若i==m-1或者i==m,则说明a[i-1]为第m大的元素,或者最大的m个元素在i左边,整个过程到这里结束。
时间复杂度计算:(n+n/2+n/4+…..)=O(n)
import java.util.Scanner;
public class T2 {
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
while(in.hasNext())
{
int n=in.nextInt();
int m=in.nextInt();
int[] arr=new int[n];
for(int i=0;i<n;i++)
{
arr[i]=in.nextInt();
}
findMaxM(arr, 0, n-1, m);
for(int i=0;i<m;i++)
{
System.out.print(arr[i]+" ");
}
}
}
static int quick(int[] arr,int l,int r)//大的放左边,小的放右边
{
int x=arr[l];
int i=l;
int j=r;
while(true)
{
while(i<j && arr[j]<=x)
j--;
if(i<j)
{
arr[i]=arr[j];
i++;
}else
break;
while(i<j && arr[i]>=x)
i++;
if(i<j)
{
arr[j]=arr[i];
j--;
}else
break;
}
arr[i]=x;
return i;
}
static void findMaxM(int[] arr,int l,int r,int m)
{
if(l>=r)
return;
int mid=quick(arr, l, r);
if(mid==m-1||mid==m)
return;
else if(mid>m)
findMaxM(arr, l, mid-1, m);
else if (mid<m-1)
findMaxM(arr, mid+1, r, m);
}
}