算法實戰(三)--求K-Pairs

題目連接如下:求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));
這裏有堆排序的說明連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章