数据结构与算法-18.数组中的第K个最大元素

18、数组中的第K个最大元素

题目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qo5hOo9a-1636533310045)(image-20211110162352475.png)]

18.0、暴力解法

直接sort排序

int findKthLargest0(vector<int>& nums, int k) 
{
    sort(nums.begin(), nums.end());
    return nums[nums.size() - k];
}
  • 时间复杂度:O(n平方)
  • 空间复杂度:O(1)

18.1、基于快速排序的选择方法

利用sort排序的原理,进行快速选择,对于数组【3,2,3,1,2,4,5,5,6】

  • 随机选择一个下标比如2,遍历一遍数组将大于等于3的都移动到2的左边,小于3的都移动到2的右边

  • 得到【5,4,5,3,6,3,1,2,2】(结果可能顺序并不是这样,只是为了说明分成两部分后仍是乱序)

  • 如果需要的是第6大的数,那就可以直接返回3了

  • 如果需要第4(在分界点前面)大的数,那就对序列【5,4,5,3,6】重复上述步骤

  • 如果需要第7(在分界点后面)大的数,那就对序列【1,2,2】重复上述步骤

最后的***最高速度***完全靠运气。。。

private:

//随机一个下标,然后将该数与最后一个数调换
int randomPartition(vector<int>& nums, int leftIndex, int rightIndex)
{
    srand((unsigned int)time(0));
    int randNum = rand() % (rightIndex - leftIndex + 1) + leftIndex;
    swap(nums[randNum], nums[rightIndex]);
    return partition(nums, leftIndex, rightIndex);
}

//根据最后一个数,将数组分为两部分,前一部分比最后一个数大,后一部分比最后一个数小
int partition(vector<int>& nums, int leftIndex, int rightIndex)
{
    int flagIndex = leftIndex;      //左右的分界线
    for (int i = leftIndex; i < rightIndex; i++)
        if (nums[i] >= nums[rightIndex])
        {
            swap(nums[flagIndex], nums[i]);
            flagIndex++;
        }
    swap(nums[flagIndex], nums[rightIndex]);
    return flagIndex;   //返回分界线坐标
}

//快速选择
int quickSelect(vector<int>& nums, int leftIndex, int rightIndex, int k)
{
    int flagIndex = randomPartition(nums, leftIndex, rightIndex);
    if (flagIndex == k)
        return nums[flagIndex];
    else
        return flagIndex < k ? quickSelect(nums, flagIndex + 1, rightIndex, k) : quickSelect(nums, leftIndex, flagIndex - 1, k);
}
public:
//基于快速排序的选择方法
int findKthLargest1(vector<int>& nums, int k)
{
    return quickSelect(nums, 0, nums.size() - 1, k - 1);
}
  • 时间复杂度:O(n)证明参见算法导论
  • 空间复杂度:O(log n)递归占用的空间

18.2、基于堆排序的选择方法

emmmm,还是去看书吧(~_~!)

  • 时间复杂度:O(n log n)
  • 空间复杂度:O(log n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值