返回介绍

solution / 0000-0099 / 0057.Insert Interval / README

发布于 2024-06-17 01:04:40 字数 12333 浏览 0 评论 0 收藏 0

57. 插入区间

English Version

题目描述

给你一个 无重叠的_ ,_按照区间起始端点排序的区间列表 intervals,其中 intervals[i] = [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval = [start, end] 表示另一个区间的开始和结束。

在 intervals 中插入区间 newInterval,使得 intervals 依然按照 starti 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。

返回插入之后的 intervals

注意 你不需要原地修改 intervals。你可以创建一个新数组然后返回它。

 

示例 1:

输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]

示例 2:

输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8][3,5],[6,7],[8,10] 重叠。

 

提示:

  • 0 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 105
  • intervals 根据 starti升序 排列
  • newInterval.length == 2
  • 0 <= start <= end <= 105

解法

方法一:排序 + 区间合并

我们可以先将新区间 newInterval 加入到区间列表 intervals 中,然后按照区间合并的常规方法进行合并。

时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是区间的数量。

class Solution:
  def insert(
    self, intervals: List[List[int]], newInterval: List[int]
  ) -> List[List[int]]:
    def merge(intervals: List[List[int]]) -> List[List[int]]:
      intervals.sort()
      ans = [intervals[0]]
      for s, e in intervals[1:]:
        if ans[-1][1] < s:
          ans.append([s, e])
        else:
          ans[-1][1] = max(ans[-1][1], e)
      return ans

    intervals.append(newInterval)
    return merge(intervals)
class Solution {
  public int[][] insert(int[][] intervals, int[] newInterval) {
    int[][] newIntervals = new int[intervals.length + 1][2];
    for (int i = 0; i < intervals.length; ++i) {
      newIntervals[i] = intervals[i];
    }
    newIntervals[intervals.length] = newInterval;
    return merge(newIntervals);
  }

  private int[][] merge(int[][] intervals) {
    Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
    List<int[]> ans = new ArrayList<>();
    ans.add(intervals[0]);
    for (int i = 1; i < intervals.length; ++i) {
      int s = intervals[i][0], e = intervals[i][1];
      if (ans.get(ans.size() - 1)[1] < s) {
        ans.add(intervals[i]);
      } else {
        ans.get(ans.size() - 1)[1] = Math.max(ans.get(ans.size() - 1)[1], e);
      }
    }
    return ans.toArray(new int[ans.size()][]);
  }
}
class Solution {
public:
  vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
    intervals.emplace_back(newInterval);
    return merge(intervals);
  }

  vector<vector<int>> merge(vector<vector<int>>& intervals) {
    sort(intervals.begin(), intervals.end());
    vector<vector<int>> ans;
    ans.emplace_back(intervals[0]);
    for (int i = 1; i < intervals.size(); ++i) {
      if (ans.back()[1] < intervals[i][0]) {
        ans.emplace_back(intervals[i]);
      } else {
        ans.back()[1] = max(ans.back()[1], intervals[i][1]);
      }
    }
    return ans;
  }
};
func insert(intervals [][]int, newInterval []int) [][]int {
  merge := func(intervals [][]int) (ans [][]int) {
    sort.Slice(intervals, func(i, j int) bool { return intervals[i][0] < intervals[j][0] })
    ans = append(ans, intervals[0])
    for _, e := range intervals[1:] {
      if ans[len(ans)-1][1] < e[0] {
        ans = append(ans, e)
      } else {
        ans[len(ans)-1][1] = max(ans[len(ans)-1][1], e[1])
      }
    }
    return
  }
  intervals = append(intervals, newInterval)
  return merge(intervals)
}
function insert(intervals: number[][], newInterval: number[]): number[][] {
  const merge = (intervals: number[][]): number[][] => {
    intervals.sort((a, b) => a[0] - b[0]);
    const ans: number[][] = [intervals[0]];
    for (let i = 1; i < intervals.length; ++i) {
      if (ans.at(-1)[1] < intervals[i][0]) {
        ans.push(intervals[i]);
      } else {
        ans.at(-1)[1] = Math.max(ans.at(-1)[1], intervals[i][1]);
      }
    }
    return ans;
  };

  intervals.push(newInterval);
  return merge(intervals);
}
impl Solution {
  pub fn insert(intervals: Vec<Vec<i32>>, new_interval: Vec<i32>) -> Vec<Vec<i32>> {
    let mut merged_intervals = intervals.clone();
    merged_intervals.push(vec![new_interval[0], new_interval[1]]);
    // sort by elem[0]
    merged_intervals.sort_by_key(|elem| elem[0]);
    // merge interval
    let mut result = vec![];

    for interval in merged_intervals {
      if result.is_empty() {
        result.push(interval);
        continue;
      }

      let last_elem = result.last_mut().unwrap();
      if interval[0] > last_elem[1] {
        result.push(interval);
      } else {
        last_elem[1] = last_elem[1].max(interval[1]);
      }
    }
    result
  }
}
public class Solution {
  public int[][] Insert(int[][] intervals, int[] newInterval) {
    int[][] newIntervals = new int[intervals.Length + 1][];
    for (int i = 0; i < intervals.Length; ++i) {
      newIntervals[i] = intervals[i];
    }
    newIntervals[intervals.Length] = newInterval;
    return Merge(newIntervals);
  }

  public int[][] Merge(int[][] intervals) {
    intervals = intervals.OrderBy(a => a[0]).ToArray();
    var ans = new List<int[]>();
    ans.Add(intervals[0]);
    for (int i = 1; i < intervals.Length; ++i) {
      if (ans[ans.Count - 1][1] < intervals[i][0]) {
        ans.Add(intervals[i]);
      } else {
        ans[ans.Count - 1][1] = Math.Max(ans[ans.Count - 1][1], intervals[i][1]);
      }
    }
    return ans.ToArray();
  }
}

方法二:一次遍历

我们可以遍历区间列表 intervals,记当前区间为 interval,对于每个区间有三种情况:

  • 当前区间在新区间的右侧,即 $newInterval[1] \lt interval[0]$,此时如果新区间还没有被加入,那么将新区间加入到答案中,然后将当前区间加入到答案中。
  • 当前区间在新区间的左侧,即 $interval[1] \lt newInterval[0]$,此时将当前区间加入到答案中。
  • 否则,说明当前区间与新区间有交集,我们取当前区间的左端点和新区间的左端点的最小值,以及当前区间的右端点和新区间的右端点的最大值,作为新区间的左右端点,然后继续遍历区间列表。

遍历结束,如果新区间还没有被加入,那么将新区间加入到答案中。

时间复杂度 $O(n)$,其中 $n$ 是区间的数量。忽略答案数组的空间消耗,空间复杂度 $O(1)$。

class Solution:
  def insert(
    self, intervals: List[List[int]], newInterval: List[int]
  ) -> List[List[int]]:
    st, ed = newInterval
    ans = []
    insert = False
    for s, e in intervals:
      if ed < s:
        if not insert:
          ans.append([st, ed])
          insert = True
        ans.append([s, e])
      elif e < st:
        ans.append([s, e])
      else:
        st = min(st, s)
        ed = max(ed, e)
    if not insert:
      ans.append([st, ed])
    return ans
class Solution {
  public int[][] insert(int[][] intervals, int[] newInterval) {
    List<int[]> ans = new ArrayList<>();
    int st = newInterval[0], ed = newInterval[1];
    boolean insert = false;
    for (int[] interval : intervals) {
      int s = interval[0], e = interval[1];
      if (ed < s) {
        if (!insert) {
          ans.add(new int[] {st, ed});
          insert = true;
        }
        ans.add(interval);
      } else if (e < st) {
        ans.add(interval);
      } else {
        st = Math.min(st, s);
        ed = Math.max(ed, e);
      }
    }
    if (!insert) {
      ans.add(new int[] {st, ed});
    }
    return ans.toArray(new int[ans.size()][]);
  }
}
class Solution {
public:
  vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
    vector<vector<int>> ans;
    int st = newInterval[0], ed = newInterval[1];
    bool insert = false;
    for (auto& interval : intervals) {
      int s = interval[0], e = interval[1];
      if (ed < s) {
        if (!insert) {
          ans.push_back({st, ed});
          insert = true;
        }
        ans.push_back(interval);
      } else if (e < st) {
        ans.push_back(interval);
      } else {
        st = min(st, s);
        ed = max(ed, e);
      }
    }
    if (!insert) {
      ans.push_back({st, ed});
    }
    return ans;
  }
};
func insert(intervals [][]int, newInterval []int) (ans [][]int) {
  st, ed := newInterval[0], newInterval[1]
  insert := false
  for _, interval := range intervals {
    s, e := interval[0], interval[1]
    if ed < s {
      if !insert {
        ans = append(ans, []int{st, ed})
        insert = true
      }
      ans = append(ans, interval)
    } else if e < st {
      ans = append(ans, interval)
    } else {
      st = min(st, s)
      ed = max(ed, e)
    }
  }
  if !insert {
    ans = append(ans, []int{st, ed})
  }
  return
}
function insert(intervals: number[][], newInterval: number[]): number[][] {
  let [st, ed] = newInterval;
  const ans: number[][] = [];
  let insert = false;
  for (const [s, e] of intervals) {
    if (ed < s) {
      if (!insert) {
        ans.push([st, ed]);
        insert = true;
      }
      ans.push([s, e]);
    } else if (e < st) {
      ans.push([s, e]);
    } else {
      st = Math.min(st, s);
      ed = Math.max(ed, e);
    }
  }
  if (!insert) {
    ans.push([st, ed]);
  }
  return ans;
}
impl Solution {
  pub fn insert(intervals: Vec<Vec<i32>>, new_interval: Vec<i32>) -> Vec<Vec<i32>> {
    let mut inserted = false;
    let mut result = vec![];

    let (mut start, mut end) = (new_interval[0], new_interval[1]);
    for iter in intervals.iter() {
      let (cur_st, cur_ed) = (iter[0], iter[1]);
      if cur_ed < start {
        result.push(vec![cur_st, cur_ed]);
      } else if cur_st > end {
        if !inserted {
          inserted = true;
          result.push(vec![start, end]);
        }
        result.push(vec![cur_st, cur_ed]);
      } else {
        start = std::cmp::min(start, cur_st);
        end = std::cmp::max(end, cur_ed);
      }
    }

    if !inserted {
      result.push(vec![start, end]);
    }
    result
  }
}
public class Solution {
  public int[][] Insert(int[][] intervals, int[] newInterval) {
    var ans = new List<int[]>();
    int st = newInterval[0], ed = newInterval[1];
    bool insert = false;
    foreach (var interval in intervals) {
      int s = interval[0], e = interval[1];
      if (ed < s) {
        if (!insert) {
          ans.Add(new int[]{st, ed});
          insert = true;
        }
        ans.Add(interval);
      } else if (st > e) {
        ans.Add(interval);
      } else {
        st = Math.Min(st, s);
        ed = Math.Max(ed, e);
      }
    }
    if (!insert) {
      ans.Add(new int[]{st, ed});
    }
    return ans.ToArray();
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文