《LeetCode之每日一题》:100.检查是否区域内所有整数都被覆盖

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:100.检查是否区域内所有整数都被覆盖相关的知识,希望对你有一定的参考价值。

检查是否区域内所有整数都被覆盖


题目链接: 检查是否区域内所有整数都被覆盖

有关题目

给你一个二维整数数组 ranges 和两个整数 left 和 right 。
每个 ranges[i] = [starti, endi] 表示一个从 starti 到 endi 的 闭区间 。

如果闭区间 [left, right] 内每个整数都被 ranges 中 
至少一个 区间覆盖,那么请你返回 true ,否则返回 false 。

已知区间 ranges[i] = [starti, endi] ,如果整数 x 满足 starti <= x <= endi ,那么我们称整数x 被覆盖了。
示例 1:

输入:ranges = [[1,2],[3,4],[5,6]], left = 2, right = 5
输出:true
解释:25 的每个整数都被覆盖了:
- 2 被第一个区间覆盖。
- 34 被第二个区间覆盖。
- 5 被第三个区间覆盖。
示例 2:

输入:ranges = [[1,10],[10,20]], left = 21, right = 21
输出:false
解释:21 没有被任何一个区间覆盖。
提示:

1 <= ranges.length <= 50
1 <= starti <= endi <= 50
1 <= left <= right <= 50

题解

法一:暴力法

bool isCovered(int** ranges, int rangesSize, int* rangesColSize, int left, int right){
    int check[51];//51为[1,50]
    memset(check, 0, sizeof(check));

    for (int i = 0; i < rangesSize; i++)
    {
        for (int j = ranges[i][0]; j <= ranges[i][1]; j++)
            check[j] = 1;//标记[l,r]出现区域
    }
    for (int i = left; i <= right; i++)
        if (check[i] == 0) return false;
    return true;
}

法二:排序

class Solution {
public:
    bool isCovered(vector<vector<int>>& ranges, int left, int right) {
        sort(ranges.begin(),ranges.end());//第一列元素进行排序
        int cnt = left;
    for (int i = 0; i < ranges.size(); i++)
    {
        if (cnt >= ranges[i][0] && cnt <= ranges[i][1])//[left,ranges[i][1]]出现
            cnt = ranges[i][1] + 1;//下一次改从ranges[i][1] + 1,ranges[i + 1][1]查找
        if (cnt > right)//找到
            return true;
    }
    return false;
    }
};

法三:优化暴力法

bool isCovered(int** ranges, int rangesSize, int* rangesColSize, int left, int right){
    int check[51];//51为[1,50]
    memset(check, 0, sizeof(check));

    for (int i = 0; i < rangesSize; i++)
    {
        int l = fmax(left,ranges[i][0]);
        int r = fmin(right,ranges[i][1]);//[l,r] 与 [left,right]交集
        for (int j = l; j <= r; j++)//
            check[j] = 1;//只更新重合的部分
    }

    //重合的部分是否包含了[left,right]所有整数值
    for (int i = left; i <= right; i++)
        if (check[i] != 1) return false;
    return true;
}

时间复杂度:时间复杂度 O(n) 与 O(n^2) 之间,故O(n方)
空间复杂度:O(n)

法四:差分数组

思路:
diff[i]覆盖整数i的的区间数量相对于覆盖 i - 1区间数量变化量。
在区间[l,r],l比l - 1多一个,r + 1比r少一个.起始下标+1,在终止下标之后-1

代码一:
参考老干妈是万能的

bool isCovered(int** ranges, int rangesSize, int* rangesColSize, int left, int right){
    int diff[52];//按照差分数组存放中,起始下标+1,在终止下标之后-1
    //起始下标0,终止下标51,共52个
    memset(diff,0,sizeof(diff));
    int idxSum[52];//前缀和
    memset(idxSum,0,sizeof(idxSum));
    
    for (int i = 0; i < rangesSize; i++)
    {
        ++diff[ranges[i][0]];
        --diff[ranges[i][1] + 1];//起始下标+1,在终止下标之后-1
    }

    for (int i = 1; i <= 51; i++)
        idxSum[i] = idxSum[i - 1] + diff[i];

     //从left到right判断是否满足sum > 0
        for(int i = left; i <= right; i++)
        {
            if(idxSum[i] <= 0) return false;
        }
    return true;
    
}

代码二:空间优化

bool isCovered(int** ranges, int rangesSize, int* rangesColSize, int left, int right){
    int diff[52];//按照差分数组存放中,起始下标+1,在终止下标之后-1
    //起始下标0,终止下标51,共52个
    memset(diff,0,sizeof(diff));
    int idxSum = 0;//前缀和

    for (int i = 0; i < rangesSize; i++)
    {
        ++diff[ranges[i][0]];
        --diff[ranges[i][1] + 1];//起始下标+1,在终止下标之后-1
    }
    for (int i = 1; i <= 50; i++)//题干条件给出1~50
    {
        idxSum += diff[i];
        if (i >= left && i <= right && idxSum <= 0) return false;
    }
    return true; 
}

以上是关于《LeetCode之每日一题》:100.检查是否区域内所有整数都被覆盖的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 每日一题 100.相同的树

《LeetCode之每日一题》:111.爬楼梯之变

《LeetCode之每日一题》:98.删除排序链表中的重复元素

《LeetCode之每日一题》:288.删除排序链表中的重复元素

《LeetCode之每日一题》:288.删除排序链表中的重复元素

《LeetCode之每日一题》:44.位1的个数