215. 数组中的第K个最大元素
权值树状数组+二分
class Solution {
int[] c;
int up;
public int findKthLargest(int[] nums, int k) {
// 离散化
// 去重+排序
Set<Integer> set = new TreeSet<>();
for(int i = 0; i < nums.length; ++ i ) set.add(nums[i]);
// 离散
Map<Integer, Integer> map = new HashMap<>();
int[] disc = new int[set.size() + 1];
up = 0;
for(Integer val : set) {
map.put(val, ++ up);
disc[up] = val;
}
// 建树
c = new int[up + 1];
for(int i = 0; i < nums.length; ++i ) {
add(map.get(nums[i]), 1);
}
k = nums.length - k + 1;
return disc[kth(k)];
}
public int kth(int k) { // 第k小,返回下标
int l = 1, r = up;
int ans = -1;
while(l <= r) {
int mid = l + ((r - l) >> 1);
int tar = getsum(mid);
if(tar >= k) { // 由于可能存在相同元素,所以当大于的时候也可能是答案
ans = mid;
r = mid - 1;
} else if(tar < k){
l = mid + 1;
}
}
return ans;
}
public int getsum(int x) {
int ans = 0;
while(x > 0) {
ans += c[x];
x -= lowbit(x);
}
return ans;
}
public void add(int x, int k) {
while(x <= up) {
c[x] += k;
x += lowbit(x);
}
}
public int lowbit(int x) {
return x & -x;
}
}
三路快速排序
class Solution {
public int findKthLargest(int[] nums, int k) {
return quickSort(nums, 0, nums.length, nums.length - k + 1);
}
public int quickSort(int[] nums, int l, int r, int k) {
int pivot = nums[l];
int i = l, lit = l, rit = r;
while(i < rit) {
if(nums[i] < pivot) {
swap(nums, i ++ , lit ++ );
} else if(nums[i] > pivot) {
swap(nums, i, -- rit);
} else {
++ i;
}
}
if(lit == l && rit == r) return pivot;
if(rit < k) return quickSort(nums, rit, r, k);
if(rit > k) return quickSort(nums, l, rit, k);
return pivot;
}
public void swap(int[] nums, int x, int y) {
if(x == y) return;
nums[x] = nums[x] ^ nums[y];
nums[y] = nums[x] ^ nums[y];
nums[x] = nums[x] ^ nums[y];
}
}