74. 数组中的第K个最大元素(堆/215)

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
假设:
1 <= k <= nums.length <= $(10)^5$;
$(-10)^4$ <= nums[i] <= $(10)^4$。
示例:输入: [3,2,1,5,6,4], k = 2;输出: 5。

【分析】
解法1:使用堆,空间换时间,时间复杂度O(nlogk)。
堆(heap,数据结构):堆是一种特殊的完全二叉树。C#中没有具体的接口或类可用于堆,可以自己建一个,使用数组来存储,为堆结构写一个上浮和下沉的方法使堆可以排序为大顶堆或小顶堆。
最大堆(大顶堆):每个节点的值都大于或等于其子节点的值。
最小堆(小顶堆):每个节点的值都小于或等于其子节点的值。
解法2:快速选择算法,时间复杂度O(n)。
快速选择算法是快速排序的一个变种,它用于在未排序的数组中找到第 k 大(或第 k 小)的元素。
分区函数式为了找到枢纽元素在数组中的最终位置,也是快排的核心算法。
每次调整后只取随机枢纽元素的一侧进行递归再排序。
就取第K个最大元素这个需求而言,不需要把整个数组排序,只要找到第K个最大元素的正确位置即可。

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
46
47
48
49
50
51
52
53
public class Solution{
//1. 使用堆
public int FindKthLargest1(int[] nums, int k){

}

//2. 快速选择算法(快速排序)
public int FindKthLargest2(int[] nums, int k){
QuickSort(nums,0,nums.Length-1,k);
return nums[nums.Length-k];
}

public void QuickSort(int[] nums, int left, int right, int k){
if(left<right){
int pviot=Partition(nums,left,right);
//快排提前终止(不需要无限递归到数组结束)
if(pviot==nums.Length-k){
return;
}
//快排分区优化
if(pviot>nums.Length-k){
QickSort(nums,left,pviot-1,k);
}else{
QickSort(nums,pviot+1,right,k);
}
}
}

public int Partition(int[] nums, int left, int right){
Swap(nums,left,(left+right)/2);//随机数和中位数的意义差不多
int pviotNum=nums[left];
while(left<right){
while(left<right && nums[right]>=pviotNum){
right--;
}
nums[left]=nums[right];
while(left<right && nums[left]<=pviotNum){
left++;
}
nums[right]=nums[left];
}
nums[left]=pviotNum;
return left;
}

public void Swap(int[] nums, int a, int b){
if(nums[a]!=nums[b]){
int temp=nums[a];
nums[a]=nums[b];
nums[b]=temp;
}
}
}

77. 买股票的最佳时机(贪心算法/121)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
假设:
1 <= prices.length <= $(10)^5$;
0 <= prices[i] <= $(10)^4$。
示例:输入:[7,1,5,3,6,4];输出:5。

【分析】
找到整数数组中的两个元素,使得后一元素减去前一元素的差最大。
时间复杂度O(n),空间复杂度O(1)。

1
2
3
4
5
6
7
8
9
10
11
public class Solution{
public int MaxProfit(int[] prices){
int minPrice=prices[0];
int maxProfit=0;
foreach(int price in prices){
minPrice=Math.Min(minPrice,price);
maxProfit=Math.Max(maxProfit,price-minPrice);
}
return maxProfit;
}
}