算法实战(三)--求K-Pairs

本文介绍了求K-Pairs问题的解决方案,重点在于使用堆排序算法。文章探讨了算法的空间复杂度,理论值为heap.size() * sizeof(int),实际值为heap.capacity(),并讨论了动态数组的内存分配机制。同时,计算了算法的时间复杂度为O(square(k) * log(k)),并提到了堆排序的相关链接。

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

题目连接如下:求K-Pairs

这道题考察的是堆排序(直接上代码):

#include<algorithm>
#include<cstdio>
#include<vector>

using namespace std;

struct element
{
    int sum ;
    unsigned int x;
    unsigned int y;
}*pelement;

static bool cmp(element a, element b)
{
    return (a.sum > b.sum);
}

element fun(vector<element>&_heap)
{
    //将数组进行堆排序;
    make_heap(_heap.begin(), _heap.end(), cmp); 
    element reslt = _heap.front();

    //弹出堆顶值;
    pop_heap(_heap.begin(), _heap.end(), cmp);
    _heap.pop_back();

    return reslt;
}

int min(int a, int b)
{
    return (a<b ? a : b);
}

class Solution {
public:
    vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        vector<element> heap(0);
        vector<pair<int, int> > reslt(0);

        if(nums1.size()==0 || nums2.size() == 0)
        {
            return reslt;
        }

        //求取取值界限;
        size_t size1= min((int)nums1.size(), k);
        size_t size2= min((int)nums2.size(), k);
        size_t threshold = min(size1*size2, k);
        //初始化堆;
         heap.reserve(size1);
        for(int i = 0; i < size1; i++)
        {
            element e;
            e.sum = nums2[0] + nums1[i];
            e.x = i;
            e.y = 0;
            heap.push_back(e);
        }

        //获取元素;
        reslt.reserve(threshold);
        while(reslt.size() != threshold)
        {
            element e = fun(heap);
            reslt.push_back(pair<int,int>(nums1[e.x], nums2[e.y]));
            if((e.y + 1) < size2)
            {
                element e1;
                e1.x = e.x;
                e1.y = e.y + 1;
                e1.sum = nums1[e1.x] + nums2[e1.y];
                heap.push_back(e1);
            }
        }

        return reslt;
    }
};

前两节中我们没有讨论时间复杂度和空间复杂度的问题,因为前两道题比较简单,这个问题是一个中等难度的问题,我们现在就要考虑的更深层次。

我们首先计算一下我们设计的算法的空间复杂度
我们所占用的空间就是维持堆运算所占用的空间,也就是vector heap所占用的大小:
理论值:
heap.szie()*sizeof(int) (0<=heap.size()<= min(k, nums1.size))
实际值:
但实际上动态数组在分配内存的时候往往会大于实际大小:
heap.capacity(),才是真正分配的内存大小,而且移除数据vector缓存区大小不会改变(vector内存分配机制)。

综上所述我们的空间复杂度为:
heap.capacity()。

然后我们在求解一下算法的时间复杂度

我们主要的时间操作是堆排序的时间:

Theap(n) 代表堆排序所用的时间, n代表数组中元素的个数;

N 代表我们执行堆排序的次数;

而在我们的代码中: N = min(nums1.size()*nums2.size(), k);

我们每次从堆中取出堆顶数据(最小和元素),然后再加入一个新的元素,直到取满k个,所以n的取值范围:
0 <= n <= min(nums1.size(),k);

我们考虑最耗时的时间:
N = k(即,nums1.size()*nums2.size()>= k), n = k(即,nums1.size() >= k),由此可得:

T(n) = k*Theap(k) ... ...1);

Theap(k) =  O(k*log(k)) ... ...(2);

根据(1)、(2)可导出:
T(n) = O(square(k)*log(k));

综上所述,算法的时间复杂度为:
T(n) = O(square(k)*log(k));
这里有堆排序的说明连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值