剑指offer27--查找数组中最小的k个数

题目: 输入n个整数,找出其中最小的k个数。

例如输入4 、5 、1、6、2、7、3 、8 这8 个数字,则最小的4 个数字是1 、2、3 、4

大神使用了两种方法,第一种我看了半天才勉强看懂的,然后自己指实现了一个方法,没能实现成功,关键是方法太巧妙了,不好想到。

package 剑指offer;
/*题目: 输入n个整数,找出其中最小的k个数。
例如输入4 、5 、1、6、2、7、3 、8 这8 个数字,则最小的4 个数字是1 、2、3 、4
*/

/*可以基于Partition函数来解决这个问题。如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,
 *比第k个数字大的所有数字都位于数组的右边。这样调整之后,位于数组中左边的k个数字就是最小的k 个数字(这k个数字不一定
 *是排序的。*/

/**
 * 题目: 输入n个整数,找出其中最小的k个数。
 * 【第一种解法】
 */
public class Test30{
	public static void getLeastNumbers(int[] input, int[] output) {
	
	    if (input == null || output == null || output.length <= 0 || input.length < output.length) {
	        throw new IllegalArgumentException("Invalid args");
	    }
	
	    int start = 0;
	    int end = input.length - 1;
	    int index = partition(input, start, end);
	    
	    // 根据Output的长度来确定目标长度
	    int target = output.length - 1;
	
	    while (index != target) {
	        if (index < target) {
	            start = index + 1;
	        } else {
	            end = index - 1;
	        }
	        
	        // 一般不会正好的,所以向左向右逐个调整
	        index = partition(input, start, end);
	    }
	
	    System.arraycopy(input, 0, output, 0, output.length);
	}
	
	
	public static void getLeastNumbers1(int[] input, int[] output){
		//判断
		if (input == null || output == null || output.length <= 0 || input.length < output.length) {
	        throw new IllegalArgumentException("Invalid args");
	    }
		
		// 确定需要查找的数据的个数k
		int k = output.length;
		
		// 找到第k最小数的具体数值是多少(没办法还是要遍历,这样就没有大神的方法好了)
		
	}
	
	/**
	 * 分区算法
	 *
	 * @param input 输入数组
	 * @param start 开始下标
	 * @param end   结束下标
	 * @return 分区位置
	 */
	private static int partition(int[] input, int start, int end) {
		// 因为不知道排在 k+1 位置的元素是哪个元素,所以先选取第一个元素为分解元素
	    int tmp = input[start];
	
	    // 下面是分界的过程
	    while (start < end) {
	        while (start < end && input[end] >= tmp) {
	            end--;
	        }
	        // 因为上面end--了,所以将input[end]的值传给input[start]来处理
	        input[start] = input[end];
	
	        while (start < end && input[start] <= tmp) {
	            start++;
	        }
	        // 和上面一样也是因为start++了,再次交换而已
	        input[end] = input[start];
	    }
	    
	    // 此时input[start]的值已经传出去了,所以将tmp放到这正好了
	    input[start] = tmp;
	    
	    // 将这个位置坐标返回
	    return start;
	}
	
	private static int partition1(int[] input, int number) {
		// 数据的交换函数初见成效
	    int start = 0;
	    int end = input.length - 1;
	
	    while (start <= end) {
	    	if(input[start] > number && input[end] < number){
	    		int temp = input[start];
	    		input[start] = input[end];
	    		input[end] = temp;
	    	}
	    	if(input[start] <= number){
	    		start++;
	    	}
	    	if(input[end] >= number){
	    		end--;
	    	}
	    }
	    return start;
	}
	
	
	public static void main(String[] args) {
	    System.out.println("第一种解法:");
	    int[] data = {4, 5, 1, 6, 2, 7, 3, 8};
		
	    int[] output = new int[4];
	    getLeastNumbers(data, output);
	    for (int i : output) {
	        System.out.print(i + " ");
	    }
	    
	    
        System.out.println();


        int[] data2 = {4, 5, 1, 6, 2, 7, 2, 8};
        partition1(data2, 5);
        for (int i : data2) {
            System.out.print(i + " ");
        }
        System.out.println();
	 
	}
}

坚持坚持再坚持

你可能感兴趣的:(java,数组)