排序

215.数组中的第k个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

1
2
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

1
2
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

leetcode原题地址

解法

  1. 是用堆排序
1
2
3
4
5
6
7
8
9
10
11
12
public int findKthLargest(int[] nums, int k) {
//小顶堆
PriorityQueue<Integer> pq=new PriorityQueue<>();
for (int num : nums) {
pq.add(num);
if(pq.size()>k){
pq.poll();
}
}
return pq.poll();

}

时间复杂度O(NlogK),空间复杂度为O(K)

  1. 使用快排
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public int findKthLargest(int[] nums, int k) {
sort(nums);
return nums[k-1];

}


private void sort(int[] arr){
doSort(arr,0,arr.length-1);
}

private void doSort(int[] arr,int left,int right){
if(left<right){
int pivot = partition(arr, left, right);
doSort(arr,left,pivot-1);
doSort(arr,pivot,right);
}
}

private int partition(int[] arr,int left,int right){

//寻找枢轴
int mid=(left+right)/2;
int pivot=arr[mid];
while (left<=right){
while (right>=0&&arr[right]<pivot){
right--;
}
while (left<arr.length&&arr[left]>pivot){
left++;
}
if(left<=right){
swap(arr, left, right);
left++;
right--;
}
}
return left;
}

private void swap(int[] arr,int a,int b){
int tmp=arr[a];
arr[a]=arr[b];
arr[b]=tmp;
}
  1. 快速选择
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public int findKthLargest(int[] nums, int k) {
int l=0;
int r=nums.length-1;
k=nums.length-k;
while (l<r){
int p = partition(nums, l, r);
if(p==k){
break;
}else if(p>k){
r=p-1;
}else {
l=p+1;
}
}
return nums[k];

}

private int partition(int[] a, int l, int h) {
int i = l, j = h + 1;
while (true) {
while (a[++i] < a[l] && i < h) {};
while (a[--j] > a[l] && j > l) {};
if (i >= j) {
break;
}
swap(a, i, j);
}
swap(a, l, j);
return j;
}
private void swap(int[] arr,int a,int b){
int tmp=arr[a];
arr[a]=arr[b];
arr[b]=tmp;
}

347. 前k个高频元素

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

1
2
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

1
2
输入: nums = [1], k = 1
输出: [1]

说明:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

leetcode原题地址

解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public List<Integer> topKFrequent(int[] nums, int k) {

//使用hashmap统计频率
HashMap<Integer, Integer> count = new HashMap();
for (int n: nums) {
count.put(n, count.getOrDefault(n, 0) + 1);
}

PriorityQueue<Integer> heap =
new PriorityQueue<Integer>((n1, n2) -> count.get(n1) - count.get(n2));

//建立堆
for (int n: count.keySet()) {
heap.add(n);
if (heap.size() > k){
heap.poll();
}

}

List<Integer> top_k = new LinkedList();
while (!heap.isEmpty()) {
top_k.add(heap.poll());
}
Collections.reverse(top_k);
return top_k;
}

75. 颜色分类

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

1
2
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?

leetcode原题地址

解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    public void sortColors(int[] nums) {
int zero = -1, one = 0, two = nums.length;
while (one < two) {
if (nums[one] == 0) {
swap(nums, ++zero, one++);
} else if (nums[one] == 2) {
swap(nums, --two, one);
} else {
++one;
}
}
}


private void swap(int[] arr,int a,int b){
int tmp=arr[a];
arr[a]=arr[b];
arr[b]=tmp;
}