Bootstrap

海量数据:TopK算法


leetcode 215

leetcode: https://leetcode-cn.com/problems/kth-largest-element-in-an-array/submissions/

方法一 快速排序法

时间复杂度O(N), 空间复杂度O(1)

class Solution {
public:
    int partition(vector<int>& nums, int low, int high)
    {
        int key = nums[low];
        int i = low, j = high;
        while (i < j)
        {
            while (i < j && nums[j] <= key) j--;
            if (i < j) nums[i++] = nums[j]; 
            while (i < j && nums[i] >= key) i++;
            if (i < j)  nums[j--] = nums[i];
        }
        nums[i] = key;
        return i;
    }

    int findKthLargest(vector<int>& nums, int k) {
        int low = 0, high = nums.size()-1;
        k--; //第k大占据第k-1位置
        while (low <= high)
        {
            int pivot = partition(nums, low, high);
            if (pivot == k) return nums[pivot];
            else if (pivot < k) low = pivot + 1;
            else //pivot > k
                high = pivot - 1;
        }
        return -1;
    }
};

方法二 堆排序法 (自己实现版 + STL版)

时间复杂度O(nlogk),空间复杂度O(N)
STL版本:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int, vector<int>, greater<int>> heap; //建立小顶堆
        for (int i = 0; i < nums.size(); i++)
        {
            heap.push(nums[i]);
            if (heap.size() > k)
                heap.pop();
        }
        return heap.top();
    }
};

手动实现堆版本:

class Solution
{
public:
    void heap_adjust(vector<int> &nums, int start, int end)
    {
        int dad = start;
        int son = 2 * dad + 1;
        while (son <= end)
        {
            if (son + 1 <= end && nums[son + 1] < nums[son])
                son = son + 1;
            else if (nums[dad] < nums[son])
                return;
            else
            {
                swap(nums[son], nums[dad]);
                dad = son;
                son = 2 * dad + 1;
            }
        }
    }

    int findKthLargest(vector<int> &nums, int k)
    {
        if (k > nums.size())
            return -1;

        //建立大小为k的小顶堆
        for (int i = k / 2 - 1; i >= 0; i--)
            heap_adjust(nums, i, k - 1);

        //加入新元素并调堆
        for (int i = k; i < nums.size(); i++)
        {
            if (nums[i] > nums[0])
            {
                swap(nums[0], nums[i]);
                heap_adjust(nums, 0, k - 1);
            }
        }
        return nums[0];
    }
};


leetcode347

https://leetcode-cn.com/problems/top-k-frequent-elements/
简单粗暴STL的小顶堆法

class Solution {
public:
    struct MyComp
    {
        bool operator()(const pair<int,int>& lhs, const pair<int,int>& rhs)
        {
            return lhs.second > rhs.second;
        }
    };

    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> hashmap;
        for (auto& e: nums)
            hashmap[e] ++;
        
        priority_queue<pair<int,int>, vector<pair<int,int>>, MyComp> heap;
        for (auto& e: hashmap)
        {
            heap.push(e);
            if (heap.size() > k)
                heap.pop();
        }

        vector<int> ans;
        while (!heap.empty())
        {
            ans.push_back(heap.top().first);
            heap.pop();
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};
;