1. 程式人生 > 其它 >LeetCode 632. 最小區間(雙指標)

LeetCode 632. 最小區間(雙指標)

題意:

你有 k 個 非遞減排列 的整數列表。找到一個 最小 區間,使得 k 個列表中的每個列表至少有一個數包含在其中。

我們定義如果 b-a < d-c 或者在 b-a == d-c 時 a < c,則區間 [a,b][c,d] 小。

 

示例 1:

輸入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
輸出:[20,24]
解釋: 
列表 1[4, 10, 15, 24, 26]24 在區間 [20,24] 中。
列表 2[0, 9, 12, 20]20 在區間 [20,24] 中。
列表 3[5, 18, 22, 30]
22 在區間 [20,24] 中。 資料範圍: nums.length == k 1 <= k <= 3500 1 <= nums[i].length <= 50 -1e5 <= nums[i][j] <= 1e5 nums[i] 按非遞減順序排列

解法:

將a[i][j]變成二元組(a[i][j],i).
那麼問題變為:
找到一個長度最小的區間[l,r],
滿足這個區間內每個序列都至少有一個二元組在裡面.

將所有二元組放在一起排序,
然後列舉r,找到一個最大的l,滿足[l,r]符合上面條件.
發現l可以雙指標維護,那麼這題就做完了.

同時,l和r的取值是離散的,
因為肯定是陣列中出現過的數, 所以只需要枚舉出現過的數即可.

code:

class Solution {
public:
    #define PI pair<int,int>
    vector<int> smallestRange(vector<vector<int>>& a) {
        int n=a.size();
        vector<int>ans;
        int milen=2e5+10;
        vector<PI>temp;
        for(int
i=0;i<n;i++){ int m=a[i].size(); for(int j=0;j<m;j++){ temp.push_back({a[i][j],i}); } } sort(temp.begin(),temp.end()); map<int,int>mp; int sum=0; int l=0; for(int i=0;i<temp.size();i++){ if(++mp[temp[i].second]==1)sum++; while(sum==n){ if(temp[i].first-temp[l].first+1<milen){ milen=temp[i].first-temp[l].first+1; ans={temp[l].first,temp[i].first}; } if(--mp[temp[l++].second]==0)sum--; } } return ans; } };