--- comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0000-0099/0057.Insert%20Interval/README.md tags: - 数组 --- <!-- problem:start --> # [57. 插入区间](https://leetcode.cn/problems/insert-interval) [English Version](/solution/0000-0099/0057.Insert%20Interval/README_EN.md) ## 题目描述 <!-- description:start --> <p>给你一个<strong> 无重叠的</strong><em> ,</em>按照区间起始端点排序的区间列表 <code>intervals</code>,其中 <code>intervals[i] = [start<sub>i</sub>, end<sub>i</sub>]</code> 表示第 <code>i</code> 个区间的开始和结束,并且 <code>intervals</code> 按照 <code>start<sub>i</sub></code> 升序排列。同样给定一个区间 <code>newInterval = [start, end]</code> 表示另一个区间的开始和结束。</p> <p>在 <code>intervals</code> 中插入区间 <code>newInterval</code>,使得 <code>intervals</code> 依然按照 <code>start<sub>i</sub></code> 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。</p> <p>返回插入之后的 <code>intervals</code>。</p> <p><strong>注意</strong> 你不需要原地修改 <code>intervals</code>。你可以创建一个新数组然后返回它。</p> <p> </p> <p><strong>示例 1:</strong></p> <pre> <strong>输入:</strong>intervals = [[1,3],[6,9]], newInterval = [2,5] <strong>输出:</strong>[[1,5],[6,9]] </pre> <p><strong>示例 2:</strong></p> <pre> <strong>输入:</strong>intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] <strong>输出:</strong>[[1,2],[3,10],[12,16]] <strong>解释:</strong>这是因为新的区间 <code>[4,8]</code> 与 <code>[3,5],[6,7],[8,10]</code> 重叠。 </pre> <p> </p> <p><strong>提示:</strong></p> <ul> <li><code>0 <= intervals.length <= 10<sup>4</sup></code></li> <li><code>intervals[i].length == 2</code></li> <li><code>0 <= start<sub>i</sub> <= end<sub>i</sub> <= 10<sup>5</sup></code></li> <li><code>intervals</code> 根据 <code>start<sub>i</sub></code> 按 <strong>升序</strong> 排列</li> <li><code>newInterval.length == 2</code></li> <li><code>0 <= start <= end <= 10<sup>5</sup></code></li> </ul> <!-- description:end --> ## 解法 <!-- solution:start --> ### 方法一:排序 + 区间合并 我们可以先将新区间 `newInterval` 加入到区间列表 `intervals` 中,然后按照区间合并的常规方法进行合并。 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是区间的数量。 <!-- tabs:start --> #### Python3 ```python 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) ``` #### Java ```java 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()][]); } } ``` #### C++ ```cpp 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; } }; ``` #### Go ```go 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) } ``` #### TypeScript ```ts 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); } ``` #### Rust ```rust 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 } } ``` #### C# ```cs 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(); } } ``` <!-- tabs:end --> <!-- solution:end --> <!-- solution:start --> ### 方法二:一次遍历 我们可以遍历区间列表 `intervals`,记当前区间为 `interval`,对于每个区间有三种情况: - 当前区间在新区间的右侧,即 $newInterval[1] \lt interval[0]$,此时如果新区间还没有被加入,那么将新区间加入到答案中,然后将当前区间加入到答案中。 - 当前区间在新区间的左侧,即 $interval[1] \lt newInterval[0]$,此时将当前区间加入到答案中。 - 否则,说明当前区间与新区间有交集,我们取当前区间的左端点和新区间的左端点的最小值,以及当前区间的右端点和新区间的右端点的最大值,作为新区间的左右端点,然后继续遍历区间列表。 遍历结束,如果新区间还没有被加入,那么将新区间加入到答案中。 时间复杂度 $O(n)$,其中 $n$ 是区间的数量。忽略答案数组的空间消耗,空间复杂度 $O(1)$。 <!-- tabs:start --> #### Python3 ```python 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 ``` #### Java ```java 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()][]); } } ``` #### C++ ```cpp 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; } }; ``` #### Go ```go 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 } ``` #### TypeScript ```ts 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; } ``` #### Rust ```rust 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 } } ``` #### C# ```cs 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(); } } ``` <!-- tabs:end --> <!-- solution:end --> <!-- problem:end -->