215. 数组中的第K个最大元素
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
提示:
1 <= k <= nums.length <= 104
-104 <= nums[i] <= 104
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
# start, end = 0, len(nums)
# if end == 1:
# return nums[0]
# if k > end:
# return -1
# def partition(low, high):
# m = randint(low, high)
# nums[low], nums[m] = nums[m], nums[low]
# qivot = nums[low]
# # 降序
# while low < high:
# while low < high and nums[high] <= qivot: high -= 1
# nums[low] = nums[high]
# while low < high and nums[low] >= qivot: low += 1
# nums[high] = nums[low]
# nums[low] = qivot
# return low
# def qsort(low, high):
# pivotloc = partition(low, high)
# if pivotloc > k - 1:
# return qsort(low, pivotloc - 1)
# elif pivotloc < k - 1:
# return qsort(pivotloc + 1, high)
# return nums[k - 1]
# return qsort(start, end - 1)
start, end = 0, len(nums)
if k > end:
return -1
def partition(low, high):
m = randint(low, high)
nums[low], nums[m] = nums[m], nums[low]
qivot = nums[low]
# 升序
while low < high:
while low < high and nums[high] >= qivot: high -= 1
nums[low] = nums[high]
while low < high and nums[low] <= qivot: low += 1
nums[high] = nums[low]
nums[low] = qivot
return low
def qsort(low, high):
pivotloc = partition(low, high)
# 因为是升序,第k大数是,n - k
if pivotloc > end - k:
return qsort(low, pivotloc - 1)
elif pivotloc < end - k:
return qsort(pivotloc + 1, high)
return nums[end - k]
return qsort(start, end - 1)
时间复杂度:O(n);空间复杂度:O(logn)
法二:大顶堆
class Solution {
public:
void maxHeapify(vector<int>& a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;
if (l < heapSize && a[l] > a[largest]) {
largest = l;
}
if (r < heapSize && a[r] > a[largest]) {
largest = r;
}
if (largest != i) {
swap(a[i], a[largest]);
maxHeapify(a, largest, heapSize);
}
}
void buildMaxHeap(vector<int>& a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {
maxHeapify(a, i, heapSize);
}
}
int findKthLargest(vector<int>& nums, int k) {
int heapSize = nums.size();
buildMaxHeap(nums, heapSize);
for (int i = nums.size() - 1; i >= nums.size() - k + 1; --i) {
swap(nums[0], nums[i]);
--heapSize;
maxHeapify(nums, 0, heapSize);
}
return nums[0];
}
};
时间复杂度:O(nlogn)
空间复杂度:O(logn)
面试题40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
class Solution:
# def selectPartition(self, arr, low, high):
# mid = (low + high) // 2
# if arr[mid] > arr[high]:
# arr[mid], arr[high] = arr[high], arr[mid]
# if arr[low] > arr[high]:
# arr[low], arr[high] = arr[high], arr[low]
# if arr[mid] > arr[low]:
# arr[mid], arr[low] = arr[low], arr[mid]
def partition(self, arr, low, high):
# self.selectPartition(arr, low, high)
# m = (low + high) // 2
m = randint(low, high)
arr[low], arr[m] = arr[m], arr[low]
pivot = arr[low]
while low < high:
while low < high and arr[high] >= pivot: high -=1
arr[low] = arr[high]
while low < high and arr[low] <= pivot: low += 1
arr[high] = arr[low]
arr[low] = pivot
return low
def selectTopK(self, arr, low, high, k):
pivotloc = self.partition(arr, low, high)
if pivotloc < k - 1:
return self.selectTopK(arr, pivotloc + 1, high, k)
elif pivotloc > k - 1:
return self.selectTopK(arr, low, pivotloc - 1, k)
return arr[:k]
def getLeastNumbers(self, arr, k):
alen = len(arr)
if k == 0 or k > alen:
return []
if alen == 0:
return []
return self.selectTopK(arr, 0, alen - 1, k)
时间复杂度:O(n), 空间复杂度:O(logn)
剑指 Offer 22. 链表中倒数第k个节点
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2. 返回链表 4->5.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
if (head == nullptr) {
return nullptr;
}
ListNode *slow = head, *fast = head;
for (int i = 0; i < k && fast; i++)
{
fast = fast->next;
}
while (slow && fast)
{
slow = slow->next; fast = fast->next;
}
return slow;
}
};
剑指 Offer 54. 二叉搜索树的第k大节点
给定一棵二叉搜索树,请找出其中第 k 大的节点的值。
示例 1:
输入: root = [3,1,4,null,2], k = 1
3
/
1 4
2
输出: 4
示例 2:
输入: root = [5,3,6,2,4,null,null,1], k = 3
5
/
3 6
/
2 4
/
1
输出: 4
限制:
1 ≤ k ≤ 二叉搜索树元素个数
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
int ans;
int cur;
public:
void dfs(TreeNode* root)
{
if (root == nullptr) {
return;
}
dfs(root->right);
if (cur == 0) {
return;
}
cur--;
if (cur == 0) {
ans = root->val;
return;
}
dfs(root->left);
}
int kthLargest(TreeNode* root, int k) {
cur = k;
dfs(root);
return ans;
}
};
时间复杂度:O(n)
空间复杂度:O(n)