面试常考算法之区间问题

时间:2022-07-24
本文章向大家介绍面试常考算法之区间问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

面试常考算法之区间问题

区间问题在面试及笔试中经常遇到,今天总结两个常见问题,那就是区间的并与交操作。

1.区间并集

对应题目是:

56.合并区间

https://leetcode-cn.com/problems/merge-intervals/

输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

简单理解就是区间合并!

合并简单呀,我们把区间想象成计算机组成原理上面的pipeline就行了,一段段区间,只要这个区间按照第一个元素(区间开始,记作first)排序,那么区间合并只需要关注已经合并区间的最后一个区间的last(第二个元素)与新区间的first(第一个元素)。

具体实现:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> ans;
        int n = intervals.size();
        if (n == 0 || n == 1) return intervals;
        sort(intervals.begin(), intervals.end(), [](auto& x, auto & y) {
            return x[0] < y[0];
        });

        ans.push_back(intervals[0]);
        for (int i = 1; i < n; i++) {
            // 拿到合并好的区间的最后一个区间
            auto& last = ans.back();
            // 新区间的第一个元素与最后一个区间的第二个元素比较
            if (intervals[i][0] > last[1]) { // 产生了新区间
                ans.push_back(intervals[i]);
            } else if (intervals[i][1] > last[1]) { 
                last[1] = intervals[i][1];
            } 
        }

        return ans;
    }
};

2.区间交集

对应题目是:

  1. 区间列表的交集

https://leetcode-cn.com/problems/interval-list-intersections/

输入:A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

简单理解就是区间交集!

算法思路:我们需要区分有交集与没有交集情况。

现有如下两个区间求交集。

[a1,a2]
[b1,b2]
  • 没有交集

那就是两种情况:1) a2 < b1 2) a1 > b2

  • 有交集 a2>=b1 && a1 <= b2

可以发现,有交集就是下面区间:

[max(a1, b1), min(a2, b2)]

具体实现如下:

class Solution {
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>>& A, vector<vector<int>>& B) {
        vector<vector<int>> ans;
        int i = 0, j = 0;
        while (i < A.size() && j < B.size()) {
            int a1 = A[i][0];
            int a2 = A[i][1];
            int b1 = B[j][0];
            int b2 = B[j][1];
            //  a2 < b1 || a1 > b2 无交集
            if (a2 >= b1 && a1 <= b2) {
                ans.push_back({max(a1, b1), min(a2, b2)});
            }
            if (b2 < a2) {
                j++;
            } else {
                i++;
            }
        }

        return ans;
    }
};