leetcode记录-排序

215. Kth Largest Element in an Array (Medium)
这道题很简单,给出最大的第K个数,从大到小排序之后return nums[k-1]就可以
,我这里用的冒泡排序,效率很低。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
      for(int i=0;i<nums.size()-1;i++)
       {
           for(int j=0;j<nums.size()-i-1;j++)
           {
               if(nums[j]<nums[j+1])
               {
                   int temp=nums[j];
                   nums[j]=nums[j+1];
                   nums[j+1]=temp;

               }
           }
       }
     return nums[k-1];
    }
};

尝试加了个flag标志后仍然效率提高不了啥。
或者直接用sort()

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
public:
    int findKthLargest(vector<int> &nums, int k)
    {
        int result = 0;
        int numsSize = int(nums.size());
        if (numsSize == 0 || k > numsSize)
        {
            return 0;
        }
        sort(nums.begin(), nums.end());
        result = nums[numsSize - k];
        return result;
    }
};

这道题目虽然简单但是常考优化:
所以这里写上两种要记住的方式:
1.堆
先介绍下优先队列
//升序队列
priority_queue <int,vector,greater > q;
就是说q这个队列里面的元素都是按升序排列好的(队头是最小的)
那么我们只需要不停的把元素放入优先队列
它会自动排序
然后稳定好队列的长度为k即可
如果长度超过k了,那就出队队头,即队列中最小的元素
最后返回队列的队头,即为第k大的元素

//代码3:优先队列/小顶堆
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        //升序的优先队列
        priority_queue <int,vector<int>,greater<int> > ascending;
        for (int &i:nums)
        {
            ascending.push(i);
            if (ascending.size()>k)
                ascending.pop();
        }
        return ascending.top();
    }
};

2.快速选择
快排的思想是:找准一个基准,把小于基准的全部丢基准左边,把大于基准的全部丢在基准的右边
完成一个基准的位置后,基准这个地方的值是不会改变的
按照快排,应该是对基准的左边和右边进行递归,实现快排

这里就可以借助快排的思想,
既然完成一次基准的排序后,基准这个地方的值是确定的
即nums[基准值的位置]一定是第(基准的位置)小的元素(是按升序排列,最左边最小)
所以我们就判断这个最后(基准值的位置)是不是(nums.size()-k)即可
如果不是,我们只需对基准的左半部分或右半部分进行递归
直到找到(基准值的位置)是(nums.size()-k)即可

//代码2:快排
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int index=nums.size()-k;//倒数第K个,这里是从小到大排序
        return quick_sort(nums,0,nums.size()-1,index);
    }
    int quick_sort(vector<int>& nums,int low,int high,int& index)
    {
        int povitkey=nums.at(low),left=low,right=high;
        while (left<right)
        {
            while (left<right)
                if (nums.at(right)<povitkey)
                {
                    nums.at(left)=nums.at(right);
                    ++left;
                    break;
                }
                else
                    --right;
            while (left<right)
                if (nums.at(left)>povitkey)
                {
                    nums.at(right)=nums.at(left);
                    --right;
                    break;
                }
                else
                    ++left;
        }
        nums.at(left)=povitkey;
        if (left==index)
            return povitkey;
        else if (left>index)
            return quick_sort(nums,low,left-1,index);
        else
            return quick_sort(nums,left+1,high,index);
    }
};

补充一个效率很高的做法:

    int findKthLargest(vector<int>& nums, int k) {

        int size = nums.size();
        for (int i = 0; i < size; i ++) {
            siftup(nums,i); // 把原来nums变成大顶堆
        }

        while(--k) {
            remove(nums);  // 依k-1次删顶
        }

        return nums[0];
    }

    void remove(vector<int>& nums) {
        int size = nums.size();
        // 最后一个元素覆盖顶元素,并删除最后一个元素
        nums[0] = nums[size-1];
        nums.erase(nums.begin() + size-1);
        siftDown(nums,0);
    }

    void siftDown(vector<int>& nums, int index) {
        int element = nums[index];
        int size = nums.size();
        int half = size >> 1;
        while (index < half) {  // index 必须是非叶子
            int leftChildIndex = (index<<1)+1;
            int rightChildIndex = leftChildIndex +1;

            //  左子节点  < 右子节点  (这里要拿到最大子节点交换)
            if (rightChildIndex < size && nums[leftChildIndex] < nums[rightChildIndex]) {
                leftChildIndex = rightChildIndex;
            }

            // 如果左右子节点不大于它就停
            if (element >= nums[leftChildIndex]) break;

            // 交换子父节点
            nums[index] =  nums[leftChildIndex];
            nums[leftChildIndex] = element;
            index = leftChildIndex;
        }
        nums[index] =  element;
    }

    void siftup(vector<int>& nums, int index) {
        int element = nums[index];

        while(index > 0) {
            int parentIndex = (index-1) >> 1;
            int parentElement = nums[parentIndex];
            if(element <= parentElement) break;

            nums[index] = parentElement;
            nums[parentIndex] = element;
            index = parentIndex;
        }
        nums[index] = element;
    }

347. Top K Frequent Elements (Medium)
451. Sort Characters By Frequency (Medium)
75. Sort Colors (Medium)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值