LeetCode 632. 最小區間(雙指標)
阿新 • • 發佈:2021-02-16
題意:
你有 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;
}
};