最小的k个数

博客给出输入n个整数找出最小K个数的问题,如输入4,5,1等8个数字,找出最小4个数字。并提供两种解决方法,一是基于快排思想调整数组,二是维护一个最大堆,根据堆内元素情况添加或替换元素。

题目描述:

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

分析:

法1:如果允许修改输入的数组,可以基于快排的思想,使得比第k个数字小的所有数字都位于数组左边,比第k个数字大的数字都位于数组右边。这样调整以后位于数组中左边的k个数字就是最小的k个数字(但这k个数字不一定是排好序的)。

public List<Integer> getLeastNumbers_Solution(int [] input, int k) {
		List<Integer> list=new ArrayList<>();
		if(input==null||input.length==0||k<=0||k>input.length)
			return list;
		int left=0,right=input.length-1;
		int index=parti(input,left,right);
		while(index!=k-1) {
			if(index<k-1) {
				left=index+1;
			}else {
				right=index-1;
			}
			index=parti(input,left,right);
		}
		Arrays.sort(input, 0, k);
		for(int i=0;i<k;i++)
			list.add(input[i]);
		return list;
		
	}
	public int parti(int []input,int left,int right) {
		if(left>right)
			return -1;
		int i=left,j=right;
		int temp=input[left];
		while(i!=j) {
			while(input[j]>=input[left]&&j>i)
				j--;
			while(input[i]<=input[left]&&i<j)
				i++;
			if(i<j) {
				int tmp=input[i];
				input[i]=input[j];
				input[j]=tmp;
			}		
		}
		input[left]=input[i];
		input[i]=temp;
		return i;
	}

法2:维护一个最大堆,当堆内数字小于k时,不断向堆内添加数字,直到堆内元素个数达到k。当堆内的数字等于k时,每次向堆内添加数字首先与堆顶元素比较,如果小于堆顶元素,则将堆顶元素移除,加入该元素;否则不做任何修改,继续遍历。

public List<Integer> getLeastNumbers_Solution1(int [] input, int k) {
		List<Integer> list=new ArrayList<>();
		int []a=new int[k];
        if(input==null||input.length==0||k>input.length)
        	return list;
        PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(k,new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				// TODO Auto-generated method stub
				return o2.compareTo(o1);
			}
		});
        for(int i=0;i<input.length;i++) {
        	if(maxHeap.size()!=k) {
        		maxHeap.offer(input[i]);
        	}else if(maxHeap.peek()>input[i]) {
        		maxHeap.poll();
        		maxHeap.offer(input[i]);
        	}
        }
        int k1=0;
        for(Integer i:maxHeap) {
        	a[k1]=i;
        	k1++;
        }
      Arrays.sort(a);
      for(int i=0;i<k;i++)
    	  list.add(a[i]);
        return list;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值