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;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值