-
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
import java.util.*; import java.util.stream.Collectors; /** * 输入n个整数,找出其中最小的K个数。 * 例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。 * Created by etf on 2018/4/9. */ public class Solution29 { /** * 直接排序 */ public ArrayList<Integer> GetLeastNumbers_Solution1(int [] input, int k) { if (k < 0 || k > input.length) { return new ArrayList<>(); } Arrays.sort(input); List<Integer> list = Arrays.stream(input) .boxed().collect(Collectors.toList()); return new ArrayList<>(list.subList(0, k)); } /** * 剪枝法 */ public ArrayList<Integer> GetLeastNumbers_Solution2(int [] input, int k) { int len = input.length; if (k <= 0 || k > len) { return new ArrayList<>(); } int start = 0; int end = len - 1; int index = partition(input, start, end); while (start < end && index != k - 1) { if (index > k - 1) { end = index - 1; index = partition(input, start, end); } else if (index < k - 1) { start = index + 1; index = partition(input, start, end); } else { break; } } return new ArrayList<>(Arrays.stream(input) .boxed().collect(Collectors.toList()).subList(0, k)); } /** * 获取 start 位置元素在数组排序后的位置 */ private int partition(int[] input, int start, int end) { int low = start; int high = end; int temp = input[low]; while (low < high) { while (low < high && temp <= input[high]) { high --; } input[low] = input[high]; while (low < high && temp >= input[low]) { low ++; } input[high] = input[low]; } input[low] = temp; return low; } public ArrayList<Integer> GetLeastNumbers_Solution3(int [] input, int k) { int len = input.length; if (k <= 0 || k > len) { return new ArrayList<>(); } //构建大顶堆 for (int i = k / 2 - 1; i >= 0 ; i--) { adjustMaxHeap(input, i, k - 1); } for (int j = k; j < len; j++) { if (input[j] < input[0]) { int temp = input[j]; input[j] = input[0]; input[0] = temp; adjustMaxHeap(input, 0, k - 1); } } return new ArrayList<>(Arrays.stream(input) .boxed().collect(Collectors.toList()).subList(0, k)); } //调整堆 private void adjustMaxHeap(int[] input, int start, int end) { int temp = input[start]; for (int i = start * 2 + 1; i <= end; i = i * 2 + 1) { if (i < end && input[i] < input[i+1]) { //取节点较大的子节点的下标 i++; } if (temp >= input[i]) { //根节点 >= 孩子中关键字较大者,调整结束 break; } else { //根节点 < 孩子中关键字较大者 input[start] = input[i]; start = i; //继续向下调整 } } input[start] = temp; } }
转载于:https://my.oschina.net/u/3839325/blog/2051067