Sweep Line (Intervals)

56. Merge Intervals

Given a collection of intervals, merge all overlapping intervals.

For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].
class Solution {
public:
    vector<Interval> merge(vector<Interval>& intervals) {
        size_t len = intervals.size();
        vector<Interval> res;
        if (!len) return res;
        sort(intervals.begin(), intervals.end(), [](Interval& a, Interval& b){return a.start < b.start;});

        int start = intervals[0].start;
        int end = intervals[0].end;

        for (size_t i = 0; i < len; ++i) {
            if(intervals[i].start <= end) {
                end = max(intervals[i].end, end);
            } else {
                res.push_back({start, end});
                start = intervals[i].start;
                end = intervals[i].end;
            }
        }
        res.push_back({start, end});
        return res;
    }
};

57. Insert Interval

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).

You may assume that the intervals were initially sorted according to their start times.

Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].

Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].

This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        size_t len = intervals.size();
        vector<Interval> res;
        if (!len) return {newInterval};
        size_t i = 0;
        for (; i < len; ++i) {
            if (intervals[i].end < newInterval.start) {
                res.push_back(intervals[i]);
            } else if (intervals[i].start <= newInterval.end){
                newInterval.start = min(newInterval.start, intervals[i].start);
                newInterval.end = max(newInterval.end, intervals[i].end);
            } else break;
        }
        res.push_back(newInterval);
        for (;i < len; ++i) res.push_back(intervals[i]);

        return res;
    }
};

252 meeting rooms

Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings.

For example,
Given [[0, 30],[5, 10],[15, 20]],
return false.

class Solution {
public:
    bool canAttendMeetings(vector<Interval>& intervals) {
        auto is_less = [](Interval& a, Interval&b) {return a.start < b.start;};
        sort(intervals.begin(), intervals.end(), is_less);

        for (size_t i = 1; i < intervals.size(); i++) {
            if (intervals[i].start < intervals[i-1].end) return false;
        }

        return true;
    }
};

128. Longest Consecutive Sequence

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example, Given [100, 4, 200, 1, 3, 2], The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> sets(nums.begin(), nums.end());
        int max_len = 0;

        for (auto n : nums) {
            if (sets.find(n) == sets.end()) continue;
            int i = n - 1;
            int j = n + 1;

            while (sets.find(i) != sets.end()) sets.erase(i--);
            while (sets.find(j) != sets.end()) sets.erase(j++);
            int cur_len = j - i - 1;
            max_len = max(cur_len, max_len);
        }

        return max_len;
    }
};

163 Missing Ranges

Given a sorted integer array where the range of elements are [lower, upper] inclusive, return its missing ranges.

For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"].

class Solution {
public:
    vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) {
        vector<string> res;
        size_t len = nums.size();
        int start = lower;
        int end = lower;
        if (!len) return {genRange(lower, upper)};

        for (size_t i = 0; i < len; ++i) {
            if (nums[i] != start) {
                end = nums[i] - 1;
                res.push_back(genRange(start, end));
            }
            start = nums[i] + 1;
        }
        if (start != upper + 1) res.push_back(genRange(start, upper));
        return res;
    }

    string genRange(int start, int end) {
        string res = to_string(start);
        if (start != end) res += "->" + to_string(end);
        return res;
    }
};

228. Summary Ranges

Given a sorted integer array without duplicates, return the summary of its ranges.

For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].

class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        vector<string> res;
        size_t len = nums.size();
        if (!len) return res;
        int start = nums[0];
        int end = nums[0];
        for (size_t i = 0; i < nums.size(); ++i) {
            if (end != nums[i]) {
                res.push_back(genSummary(start, end - 1));
                start = nums[i];
            }
            end = nums[i] + 1;
        }
        res.push_back(genSummary(start, end - 1));
        return res;
    }

    string genSummary(int start, int end) {
        string res = to_string(start);
        if (start != end) res += "->" + to_string(end);
        return res;
    }
};

352. Data Stream as Disjoint Intervals

Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen so far as a list of disjoint intervals.

For example, suppose the integers from the data stream are 1, 3, 7, 2, 6, ..., then the summary will be:

[1, 1]
[1, 1], [3, 3]
[1, 1], [3, 3], [7, 7]
[1, 3], [7, 7]
[1, 3], [6, 7]

Follow up: What if there are lots of merges and the number of disjoint intervals are small compared to the data stream's size?

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class SummaryRanges {
public:
    /** Initialize your data structure here. */
    SummaryRanges() {

    }

    void addNum(int val) {
        auto it = intervals.lower_bound(Interval(val, val));
        if (it != intervals.begin() && (--it)->end + 1< val) ++it;
        int start = val, end = val;
        while (it != intervals.end() && val + 1 >= it->start && val - 1 <= it->end) {
            start = min(it->start, start);
            end = max(it->end, end);
            it = intervals.erase(it);
        }
        intervals.insert(Interval(start, end));
    }

    vector<Interval> getIntervals() {
        vector<Interval> res;
        for (auto it : intervals) res.push_back(it);
        return res;
    }

private:
    struct cmp {
      bool operator()(Interval a, Interval b) {
          return a.start < b.start;
      } 
    };

    set<Interval, cmp> intervals;
};

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * vector<Interval> param_2 = obj.getIntervals();
 */

The interval covering problem

you are given a set of closed intervals. Design an efficient algorithm for finding a minimum sized set of numbers that cover all the intervals

Greedy algorithm:
intuition: focus on extreme points. at the time we must have a point: when a line ends ==> sort based on right end.

vector<int> FindMinimumVisits(vector<Interval> intervals) {
  if (intervals.empty()) {
    return {};
  }

  // Sort intervals based on the right endpoints.
  sort(intervals.begin(), intervals.end(),
       [](const Interval& a, const Interval& b) -> bool {
         return a.right < b.right;
       });
  vector<int> visits;
  int last_visit_time = intervals.front().right;
  visits.emplace_back(last_visit_time);
  for (const Interval& interval : intervals) {
    if (interval.left > last_visit_time) {
      // The current right endpoint, last_visit_time, will not cover any more
      // intervals.
      last_visit_time = interval.right;
      visits.emplace_back(last_visit_time);
    }
  }
  return visits;
}

The view from above (EPI P426)

sweep line + BST

struct LineSegment {
  int left, right;  // Specifies the interval.
  int color;
  int height;
};

class Endpoint {
 public:
  bool operator<(const Endpoint& that) const {
    return Value() < that.Value();
  }

  int Value() const { return isLeft_ ? line_->left : line_->right; }

  bool isLeft_;
  const LineSegment* line_;
};

vector<LineSegment> CalculateViewFromAbove(const vector<LineSegment>& A) {
  vector<Endpoint> sorted_endpoints;
  for (const LineSegment& a : A) {
    sorted_endpoints.emplace_back(Endpoint{true, &a});
    sorted_endpoints.emplace_back(Endpoint{false, &a});
  }
  sort(sorted_endpoints.begin(), sorted_endpoints.end());

  vector<LineSegment> result;
  int prev_xaxis = sorted_endpoints.front().Value();  // Leftmost end point.
  unique_ptr<LineSegment> prev = nullptr;
  map<int, const LineSegment*> active_line_segments;
  for (const Endpoint& endpoint : sorted_endpoints) {
    if (!active_line_segments.empty() && prev_xaxis != endpoint.Value()) {
      if (prev == nullptr) {  // Found first segment.
        prev = make_unique<LineSegment>(
            LineSegment{prev_xaxis, endpoint.Value(),
                        active_line_segments.crbegin()->second->color,
                        active_line_segments.crbegin()->second->height});
      } else {
        if (prev->height == active_line_segments.crbegin()->second->height &&
            prev->color == active_line_segments.crbegin()->second->color &&
            prev_xaxis == prev->right) {
          prev->right = endpoint.Value();
        } else {
          result.emplace_back(*prev);
          *prev = {prev_xaxis, endpoint.Value(),
                   active_line_segments.crbegin()->second->color,
                   active_line_segments.crbegin()->second->height};
        }
      }
    }
    prev_xaxis = endpoint.Value();

    if (endpoint.isLeft_ == true) {  // Left end point.
      active_line_segments.emplace(endpoint.line_->height, endpoint.line_);
    } else {  // Right end point.
      active_line_segments.erase(endpoint.line_->height);
    }
  }

  // Output the remaining segment (if any).
  if (prev) {
    result.emplace_back(*prev);
  }
  return result;
}

results matching ""

    No results matching ""