牛客刷题日记【滑动窗口的最大值|寻找第K大|最小的K个数】

BM47 寻找第K大

有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。

给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。

要求:时间复杂度 O(nlogn)O(nlogn),空间复杂度 O(1)O(1)

数据范围:0≤n≤10000≤n≤1000, 1≤K≤n1≤Kn,数组中每个元素满足 0≤val≤100000000≤val≤10000000

思考:

这道题目要求为nlogn,这是我的两种解题思路

  1. 对数组进行快排,直接输出a[n-1]
  2. 将数组加入优先队列中,输出至第n个元素

代码:

priority_queue

#include <queue>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param a int整型vector 
     * @param n int整型 
     * @param K int整型 
     * @return int整型
     */
    
    // bool cmp (int a, int b) {
    //     return a > b ? true : false ;
    // }
    
    struct cmp {
        bool operator()(int a, int b) {
            return a < b ? true : false ;       
        }
    };

    int findKth(vector<int>& a, int n, int K) {
        // write code here

        std::priority_queue<int, vector<int> , cmp> pq;

        for (int i = 0;i < n;i++)   pq.push(a[i]);

        for (int i = 0;i < K-1;i++) {
            std::cout << pq.top() << std::endl;
            pq.pop();
        }

        return pq.top();
    }
};

qSort

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param a int整型vector 
     * @param n int整型 
     * @param K int整型 
     * @return int整型
     */
    
    void qSort(vector<int>& num, int begin, int end) {
        if (begin > end) return;

        int t = num[begin];  // 数轴元素的选择有多种方式,这里默认首元素
        int left = begin;
        int right = end;

        while (left < right)
        {
            while (left < right && t > num[right])  right--;
            if (left < right)
                num[left++] = num[right];

            while (left < right && t < num[left])   left++;
            num[right--] = num[left];

        }
        num[left] = t;

        qSort(num, begin, left-1);
        qSort(num, left+1, end);

        return;
    }
    
    int findKth(vector<int>& a, int n, int K) {
        // write code here

        qSort(a,0,n-1);

        return a[K-1];
    }
};

BM46 最小的K个数

给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。

数据范围:0≤k,n≤100000≤k,n≤10000,数组中每个数的大小0≤val≤10000≤val≤1000

要求:空间复杂度 O(n)O(n) ,时间复杂度 O(nlogk)O(nlogk)

思考:

先排序,再加入

代码:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param input int整型vector 
     * @param k int整型 
     * @return int整型vector
     */
    
    void qSort(vector<int>& num, int begin, int end) {
        if (begin > end) return ;
        int t = num[begin];

        int l = begin, r = end;

        while (l < r) 
        {
            while (l < r && t < num[r]) r--;
            if (l < r)  num[l++] = num[r];

            while (l < r && t > num[l]) l++;
            num[r--] = num[l];

        }
        num[l] = t;

        qSort(num, begin, l-1);
        qSort(num, l+1, end);

        return;
    }
    
    vector<int> GetLeastNumbers_Solution(vector<int>& input, int k) {
        // write code here

        qSort(input,0,input.size()-1);

        vector<int> res;

        for (int i = 0;i < k;i++) res.push_back(input[i]);

        return res;
    }
};

BM45 滑动窗口的最大值

给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。

例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

窗口大于数组长度或窗口长度为0的时候,返回空。

数据范围: 1≤n≤100001≤n≤10000,0≤size≤100000≤siz**e≤10000,数组中每个元素的值满足 ∣val∣≤10000∣val∣≤10000

要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

思考:

看了一下题目和思路,大概明白是用堆去做,可惜没实现出来,无奈看看题解。

学到的内容,目前对于vector等数据结构的理解,还停留在只存储单一元素。

这道题可以构建一个{元素+下标}的结构体,然后用优先队列(堆)来维护。

代码:

#include <queue>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param num int整型vector 
     * @param size int整型 
     * @return int整型vector
     */

    struct d {
        int num;
        int id;
    };

    struct cmp {
        bool operator()(d a,d b){
            return a.num < b.num;
        }
    };

    
    vector<int> maxInWindows(vector<int>& num, int size) {
        // write code here

        vector<int> res;

        if (size > num.size() || !size) return res;

        priority_queue<d, vector<d>, cmp> pq;
        int idx = 0;
        for (int i = 0;i < num.size();i++) 
        {
            d tmp;
            tmp.id = i;
            tmp.num = num[i];

            pq.push(tmp);

            if (i >= size-1) {
                while (!pq.empty() && pq.top().id < idx) { // 保证最大值元素在窗口内
                    pq.pop();
                }

                res.push_back(pq.top().num);
                idx++;
            }
        }

        return res;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值