215. Kth Largest Element in an Array(找出第K大的数)

本文介绍了三种不同的方法来寻找数组中的第K大元素:快速排序、分治算法及使用map进行桶排序。同时展示了如何利用C++标准库中的数据结构实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

既然是要找到第K大的数,那么自然想到先排好序再输出。于是写了一个快速排序算法:

void mySort(vector<int>& vec, int left, int right) {
    int i = left, j = right;
    int mid = vec[(left + right) / 2];
    while (i <= j) {
        while (vec[i] < mid)
            i++;
        while (vec[j] > mid)
            j--;
        if (i <= j) {
            int tmp = vec[i];
            vec[i] = vec[j];
            vec[j] = tmp;
            i++;
            j--;
        }
    }
    if (left < j)
        mySort(vec, left, j);
    if (i < right)
        mySort(vec, i, right);
}

class Solution {
public:
	int findKthLargest(vector<int>& nums, int k) {
		int len = nums.size();
        mySort(nums, 0, len - 1);
        return nums[len - k];
	}
};

虽然很快就AC了,但是毕竟在学分治算法,想尝试一下用分治怎么用。于是上网找了此题的分治做法,主要是通过pivot来重构数组,想法很妙:寻找第K大的数,即寻找降序数组中位于第K位置的值。要重构数组,先找一个数当成pivot,比它大的放在数组左边,比它小的放在数组右边,不断重复直到pivot位于数组的第K个位置。

void swap(vector<int>& vec, int i, int j) {
    int tmp = vec[j];
    vec[j] = vec[i];
    vec[i] = tmp;
}

int partition(vector<int>& vec, int left, int right) {
    int pivot = vec[left];
    int i = left + 1, j = right;
    while (i <= j) {
        if (vec[i] < pivot && vec[j] > pivot) {
            swap(vec, i, j);
            i++;
            j--;
        }
        if (vec[i] >= pivot)
            i++;
        if (vec[j] <= pivot)
            j--;
    }
    swap(vec, left, j);
    return j;
}

class Solution {
public:
	int findKthLargest(vector<int>& nums, int k) {
        int len = nums.size();
        int l = 0, r = len - 1;
		while (1) {
            int pos = partition(nums, l, r);
            if (pos == k - 1)
                return nums[pos];
            else if (pos > k - 1)
                r = pos - 1;
            else if (pos < k - 1)
                l = pos + 1;
        }
	}
};


其实用map来解这道题也是很方便的,算法思想有点类似桶排序,将数组元素当作键,元素出现的次数当作值,保存起来,最后输出第n-k+1小的数(即第k大的数):

class Solution {
public:
	int findKthLargest(vector<int>& nums, int k) {
        map<int, int> m;
        int len = nums.size();
        for (int j = 0; j < len; j++) {
            m[nums[j]]++;
        }
        map<int, int>::iterator it = m.begin();
        k = len - k + 1;
        while (k > (it->second)) {
            k = k - (it->second);
            it++;
        }
        return it->first;
	}
};

除此之外,C++也有许多自带排序的数据结构,例如set、priority_queue,虽然对做算法题没有什么作用,但是可以作为一个实用的数据结构供我们今后使用。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        multiset<int> q(nums.begin(), nums.end());
        multiset<int>::iterator it;
        int flag = 1;
        int len = nums.size();
        for (it = q.begin(); it != q.end(); it++, flag++) {
            if (flag == len - k + 1)
                break;
        }
        return *it;
    }
};
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> q(nums.begin(), nums.end());
        for (int i = 0; i < k - 1; ++i) {
            q.pop();
        }
        return q.top();
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值