Open songyy5517 opened 1 year ago
思路1:基于快速排序的数组排列
复杂度分析:
最坏情况下的时间复杂度也为 $O(N)$ :情况最差时,每次的划分点都是最大值或最小值,一共需要划分 $k$ 次,而一次划分需要线性的时间复杂度,所以最坏情况下时间复杂度为 $O(N)$。 $(n-1) + (n-2) + ...+ (n-k)$
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param input int整型一维数组
* @param k int整型
* @return int整型ArrayList
*/
public ArrayList<Integer> GetLeastNumbers_Solution (int[] input, int k) {
// write code here
// Approach: Sort & Pick
// 1. Exceptions
ArrayList<Integer> res = new ArrayList();
if (input == null || input.length == 0 || k == 0)
return res;
if (k > input.length)
k = input.length;
// 2. Sort
quickSort(input, 0, input.length - 1, k);
for(int i = 0; i < k; i++)
res.add(input[i]);
return res;
}
// 以start为基准元素,对范围[i,j]的元素快速排序,直到基准元素的下标等于k-1
// 这里必须递归,不然首尾边界永远不会变
void quickSort(int[] input, int start, int end, int k){
int index = partition(input, start, end);
if (index == k-1)
return ;
if (index < k - 1){
quickSort(input, index+1, end, k);
}
else{
quickSort(input, start, index-1, k);
}
return;
}
// 快排的partition操作
int partition(int[] input, int start, int end){
int criterion = input[start];
int left = start + 1, right = end;
while (left <= right){
while (left <= right && input[left] <= criterion) left++;
while (right >= left && input[right] >= criterion) right--;
if (left >= right)
break;
int temp = input[left];
input[left] = input[right];
input[right] = temp;
}
// 将基准元素放置其对应的位置
input[start] = input[right];
input[right] = criterion;
return right;
}
}
思路2:基于堆排序的数组排列
复杂度分析
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param input int整型一维数组
* @param k int整型
* @return int整型ArrayList
*/
public ArrayList<Integer> GetLeastNumbers_Solution (int[] input, int k) {
// write code here
// Approach: Heap Sort
// 1. Exceptions
ArrayList<Integer> res = new ArrayList();
if (input == null || input.length == 0 || k == 0)
return res;
if (k > input.length)
k = input.length;
// 2. Define Max Heap
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((x, y)->(y - x));
for(int i = 0; i < input.length; i++){
if (i < k){
maxHeap.add(input[i]);
continue;
}
if (input[i] < maxHeap.peek()){
maxHeap.remove();
maxHeap.add(input[i]);
}
}
while (!maxHeap.isEmpty())
res.add(maxHeap.remove());
return res;
}
}
2023/2/8
2023/11/14
2024/2/28
2024/3/5
while (left <= right && ....)
2024/3/22
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
示例 2:
分析 这道题需要我们找出数组中最小的k个数。一个很直接的想法是对数组先排序,再按顺序取出最小的k个数。但这种方法的时间复杂度取决于具体的排序算法。考虑到快速排序的性质,每次选取一个基准元素pivot,可以将整个数组分成两个部分,其左边的元素都小于基准元素,右边的元素都大于基准元素。因此,我们无需对整个数组进行排序,只需找到索引为k - 1的基准元素即可,从而降低了时间复杂度。