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個節點](https://leetcode.cn/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/)
輸入一個鏈表,輸出該鏈表中倒數第k個節點。爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾節點是倒數第1個節點。
例如,一個鏈表有 6 個節點,從頭節點開始,它們的值依次是 1、2、3、4、5、6。這個鏈表的倒數第 3 個節點是值爲 4 的節點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 k = 2. 返回鏈表 4->5.
```c++
/**
* 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)