双指针——区间交集

很经典的一道题目

但我初次遇见的时候就觉得这个模拟写出来非常麻烦就没去学习(菜🐕表示只能模拟

后来也是大概遇到了两三次也是忽视了(当时想的是,做这种模拟题还不如学我算法刷我图)

然后这次在数据结构里面遇到这个题,标识着“双指针”

我就理所应当的考虑着两层遍历i,j指针,然后(一通乱写,我是真的在去一步一步老实巴交地找区间)

先上学习后的标准双指针code:

 

class Solution
{
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>> &firstList, vector<vector<int>> &secondList)
    {
        int p = firstList.size(), q = secondList.size(), i = 0, j = 0;
        vector<vector<int>> ans;
        while (i < p && j < q)
        {
            int l = max(firstList[i][0], secondList[j][0]);
            int r = min(firstList[i][1], secondList[j][1]);
            if (l <= r)
                ans.emplace_back(vector<int>{l, r});
            if (firstList[i][1] > secondList[j][1])
                j++;
            else
                i++;
        }
        return ans;
    }
};
View Code

 

这个标准算法时间复杂度为O(n+m)

然后我自己琢磨两小时写的算法(狗屁)时间复杂度为O(n+m*log(n))

思路是这样的(被疯狂卡边界debug一个小时):

  先把一个数组转换为一维数组a,

  遍历第二个数组的上界r,下届l,

    在一维数组a里面二分找[x,y]满足[x,y]为[l,r]的子区间

      且通过奇偶性判断该届时原数组的上界还是下届

         分三段:

             头:确定开头是a[x]还是l

             中:连续区间长度:[x+x%2,(y+1)/2*2)【是的没看错很复杂的样子】

             尾:确定结尾是否添加[a[y],l]

         然后即便实现了这三段也是被疯狂卡边界

      还需要预处理y>x的情况和数组为空的情况。

最后,在处理二分查找的时候,发现我居然一直误解了lower_bound和upper_bound函数的用法:

 

            递增数组中lower_bound第一个大于等于x的下标
            递减数组中lower_bound第一个小于等于x的下标

            递增数组中upper_bound第一个大于x的下标
            递减数组中upper_bound第一个小于x的下标
虽然但是吧,我还是写出来并AC了:
class Solution
{
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>> &firstList, vector<vector<int>> &secondList)
    {
        vector<int> a;
        vector<vector<int>> ans;
        if (firstList.size() == 0 || secondList.size() == 0)
            return ans;
        for (auto i : firstList)
            for (auto j : i)
                a.emplace_back(j);
        for (int i = 0; i < secondList.size(); ++i)
        {
            int l = secondList[i][0], r = secondList[i][1];
            int x = lower_bound(a.begin(), a.end(), l) - a.begin(); //大于等于左边界
            int y = upper_bound(a.begin(), a.end(), r) - a.begin(); //小于等于右边界
            if (y == a.size() || a[y] > r)
                y--;
            if (x % 2 && y < x && y >= 0 && x < a.size())
                ans.emplace_back(secondList[i]);
            else
            {
                int z = x % 2;
                if (z)
                    ans.emplace_back(vector<int>{l, min(r, a[x])}); // x奇数开
                for (int j = x + z; j < (y + 1) / 2 * 2; j += 2)    // x+z保证偶数开
                    ans.emplace_back(vector<int>{a[j], a[j + 1]});
                if ((y - x - z) % 2 == 0)
                    ans.emplace_back(vector<int>{a[y], r});
            }
        }
        return ans;
    }
};
简洁但丑陋的代码

【Over】

 

posted @ 2022-03-14 15:29  Renhr  阅读(69)  评论(0)    收藏  举报