1. 程式人生 > >LeetCode 632. Smallest Range

LeetCode 632. Smallest Range

題意:給定k個排好序的陣列,求出長度最小的range [l,r]使得每個陣列至少有一個元素出現在range內。

很明顯的一個observation是l,r一定是陣列中的數。如果只有一個數組,用兩個pointer就OK。列舉r,隨著r的增加,l不斷右移保證cover所有的陣列即可。

開始在糾結一維陣列中的r=r+1情況怎麼對應到k個數組中。

對於K個數組,這種case和merge k sorted lists很像。l右移時每次都指向最小的元素,所以可以通過priority queue實現。如果tmp=que.top()是某個陣列k在queue中唯一的的元素,說明l無法再向右移,且是當前的r下最大的l,為了保證cover所有的陣列,需要在que push tmp之後的元素tmp_next,如果r比tmp_next小,則update r。

初始化時把K個數組的第一個元素都push進que中,pointer指向每個陣列的開頭。如果某一個數組k的pointer已經指向末尾,說明l無法再向右移,且r再向右移只會讓區間更大,所以這種情況下可以直接結束。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
#include<stack>
using namespace std;

//leetcode 632. Smallest Range
const int maxn=3510;
int T;
int N;
int M;
class CompareDist
{
public:
    bool operator()(pair<int,int> n1,pair<int,int> n2) {
        if(n1.first==n2.first)
        {
            return n1.second>n2.second;
        }
        return n1.first>n2.first;
    }
};
class Solution {
public:
    int freq[maxn];
    int pointer[maxn];
    priority_queue<pair<int,int>,vector<pair<int,int>>,CompareDist>que;
    vector<int> smallestRange(vector<vector<int>>& nums) {

        int left=nums[0][0];
        int right=nums[0][0];
        vector<int>range={-100000,100000};
        memset(freq,0,sizeof(freq));
        memset(pointer,0,sizeof(pointer));
        while(!que.empty())
        {
            que.pop();
        }
        for(int i=0;i<nums.size();i++)
        {
            pair<int,int>tmp=make_pair(nums[i][pointer[i]],i);
            pointer[i]++;
            que.push(tmp);
            left=min(left,tmp.first);
            right=max(right,tmp.first);
            freq[i]++;
        }
        while(!que.empty())
        {
            while(true)
            {
                pair<int,int>tmp=que.top();
                if(freq[tmp.second]>1)
                {

                    que.pop();
                    freq[tmp.second]--;
//                    cout<<"pop "<<tmp.first<<endl;
                }
                else
                {
                    left=tmp.first;
//                    cout<<"left "<<left<<" right "<<right<<endl;
                    if(range[1]-range[0]>right-left)
                    {
                        range[0]=left;
                        range[1]=right;
                    }
                    break;
                }

            }
            pair<int,int>tmp=que.top();
            if(pointer[tmp.second]!=nums[tmp.second].size())
            {
                que.push(make_pair(nums[tmp.second][pointer[tmp.second]],tmp.second));
                right=max(right,nums[tmp.second][pointer[tmp.second]]);
//                cout<<"push "<<nums[tmp.second][pointer[tmp.second]]<<" from "<<tmp.second<<endl;
                pointer[tmp.second]++;
                freq[tmp.second]++;
            }
            else
            {
                break;
            }
        }
//        cout<<range[0]<<" "<<range[1]<<endl;
        return range;
    }
};
int main()
{
//    priority_queue<pair<int,int>,vector<pair<int,int>>,CompareDist>que;
//    for(int i=0;i<10;i++)
//    {
//        pair<int,int>tmp=make_pair(2,i);
//        que.push(tmp);
//    }
//    while(!que.empty())
//    {
//        pair<int,int>tmp=que.top();
//        que.pop();
//        cout<<tmp.first<<" "<<tmp.second<<endl;
//    }
//    return 0;
    freopen("input.txt","r",stdin);
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        cin>>N;
        vector<vector<int> >matrix;
        for(int i=0;i<N;i++)
        {
            cin>>M;
            matrix.push_back(vector<int>());
            for(int j=0;j<M;j++)
            {
                int tmp;
                cin>>tmp;
                matrix[i].push_back(tmp);
            }

        }
        Solution sol;
        sol.smallestRange(matrix);
//        cout<<"Case #"<<ca<<": "<<sol.largestRectangleArea(matrix)<<endl;
    }
    return 0;
}