剑指Offer--最小的k个数

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


思路一:
利用parition函数,分割找到第k个位置,那么k位置之前的就是k个未排序的小数,参看快速排序;


import java.util.ArrayList;

/*快速排序*/
public class 最小的k个数 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		int[] input = {4,5,1,6,2,7,3,8};
		int[] input = {4,5,1,6,2,7,3,8};
		ArrayList<Integer> ans = GetLeastNumbers_Solution(input, 4);
		for (int i = 0; i < ans.size(); i++) {
			System.out.print(ans.get(i)+" ");
		}
	}

    public static ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
    	ArrayList<Integer> answer = new ArrayList<>();
    	if (input==null||k>input.length||k<0) {
			return answer;
		}
    	int index = partition(input,0,input.length-1);
    	while (index!=k-1) {
			if (index>k-1) {
				index = partition(input, 0, index-1);
			}else {
				index = partition(input, index+1, input.length-1);
			}
		}
    	
//    	Arrays.sort(input);
    	for (int i = 0; i < k; i++) {
			answer.add(input[i]);
		}
		return answer;
    }

    /*partition算法*/
	private static int partition(int[] input, int low, int high) {
		// TODO Auto-generated method stub
		int pivot = input[low];
		//注意这里的<号,不是小于等于号
		while (low<high) {
			while (low<high&&input[high]>=pivot) {
				high--;
			}
//			swap(input, high, low);
			input[low]=input[high];
			while (low<high&&input[low]<=pivot) {
				low++;
			}
//			swap(input, low, high);
			input[high]=input[low];
		}
		input[low]=pivot;
		return low;
	}
	
	private static void swap(int[] input, int i,int j) {
		int temp = input[i];
		input[i] = input[j];
		input[j] = temp;
	}
}

思路二:
创建一个容量为K的容器,把数组挨个放进来,如果容量满了,就把容器最大的数和要放入的那个数比较,容器里的更小,就继续遍历下一个数,容器的更大,就删除这个数,放入数组的数;这里容器使用大堆,排除最大的数,为logk;

第一步:创建一个k容量的大堆,从数组先放入前k个数;

第二步:挨个取出数组K以后的数和堆最大的数比较;堆里的大就和数组的数互换,然后调整堆;

n个数,复杂度为n*logk;参考 堆排序


import java.util.ArrayList;

public class 最小的k个数2 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] input = {4,5,1,6,2,7,3,8};
		int k = 0;
		ArrayList<Integer> ans = GetLeastNumbers_Solution(input,k);
		for (int i = 0; i < k; i++) {
			System.out.print(ans.get(i)+" ");
		}
	}

    public static ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
    	ArrayList<Integer> sort = new ArrayList<>();
    	if (k<=0||k>input.length||input==null) {
			return sort;
		}
    	sort = heapsort(input,k);
		return sort;
    }

	private static ArrayList<Integer> heapsort(int[] input, int k) {
		// TODO Auto-generated method stub
		//创建一个大顶堆容器maxheap
		int maxheap[] = new int[k];
		//初始化,填入数据;
		for (int i = 0; i < k; i++) {
			maxheap[i]= input[i];
		}
		//maxheap数组构建成一个大顶堆
		for (int i = (maxheap.length-1)/2; i >= 0 ; i--) {//这里是maxheap.length-1/2
			heapadjust(maxheap,i,maxheap.length);
		}
		//把input数组剩下的数挨个遍历和大顶堆的最大数比较
		for (int i = k; i < input.length; i++) {
			if (input[i]<maxheap[0]) {
				maxheap[0]	=input[i];//大顶堆的数字比被遍历的大,则删除,放入被遍历的数字
				heapadjust(maxheap, 0, maxheap.length);
			}
		}
		ArrayList<Integer> ans = new ArrayList<>();
		for (int i = 0; i < maxheap.length; i++) {
			ans.add(maxheap[i]);
		}
		return ans;
	}

	/*从i位置,从下到上,从左到右调整*/
	private static void heapadjust(int[] maxheap, int i, int length) {
		// TODO Auto-generated method stub
		
			int temp = maxheap[i];
			for (int j = i*2; j < length; j*=2) {
				if (j+1<length&&maxheap[j]<maxheap[j+1]) {
					j++;//说明右边节点值大于左边节点值,让j+1定位到右边节点;
				}
				if (temp>=maxheap[j]) {
					break;
				}
				maxheap[i]=maxheap[j];
				i=j;
			}
			maxheap[i] = temp;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obession

觉得有用可以打赏咖啡一杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值