目录
15. 三数之和
https://leetcode-cn.com/problems/3sum/submissions/
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例:给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:[[-1, 0, 1],[-1, -1, 2]]
思路
该题主要的难点是如何去重
一:先将数组排序,然后二重循环+哈希表寻找可行解,并借助set的特性进行去重。也在过程中进行了类似剪枝操作,但是没去除干净。
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if len(nums) < 3:
return []
res = []
nums = sorted(nums)
rec = set([nums[0]])
unique_rec = set()
for i in range(1, len(nums)):
if i >= 3 and nums[i] == nums[i - 2]:
continue
for j in range(i + 1, len(nums)):
if j >= i + 2 and nums[j] == nums[j - 1]:
continue
t = 0 - nums[i] - nums[j]
if t in rec and (t, nums[i], nums[j]) not in unique_rec:
res.append([t, nums[i], nums[j]])
unique_rec.add((t, nums[i], nums[j]))
rec.add(nums[i])
return res
二:借助两数之和的思路,用双指针。先排序,此处排序是方便在过程中就可以剔除重复解,固定一个数,用双指针寻找可行解。
令左指针 l=i+1,右指针 r=n−1,当 l<r 时,执行循环:当 nums[i]+nums[l]+nums[r]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 l,r 移到下一位置,寻找新的解。
while l < r and nums[l] == nums[l + 1]:
l += 1
while l < r and nums[r] == nums[r - 1]:
r -= 1
l += 1
r += 1
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
if len(nums) < 3:
return []
nums = sorted(nums)
res = []
for i in range(len(nums)):
if i > 0 and nums[i] == nums[i - 1]:
continue
l, r = i + 1, len(nums) - 1
while l < r:
if nums[i] + nums[l] + nums[r] < 0:
l += 1
elif nums[i] + nums[l] + nums[r] > 0:
r -= 1
else:
res.append([nums[i], nums[l], nums[r]])
lv, rv = nums[l], nums[r]
l += 1
r -= 1
while l < r and nums[l] == lv:
l += 1
while l < r and nums[r] == rv:
r -= 1
return res
18. 四数之和
https://leetcode-cn.com/problems/4sum/
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。注意:答案中不可以包含重复的四元组。
示例:给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。满足要求的四元组集合为:[[-1, 0, 0, 1],[-2, -1, 1, 2], [-2, 0, 0, 2]]。
思路
一:借助两数之和的思路,用双指针。先排序,此处排序是方便在过程中就可以剔除重复解,固定两个数,用双指针寻找可行解,时间复杂度O(n^3)。
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
if len(nums) < 4:
return []
nums = sorted(nums)
res = []
for i in range(len(nums)):
if i >= 1 and nums[i] == nums[i - 1]:
continue
for j in range(i + 1, len(nums)):
if j > i + 1 and nums[j] == nums[j - 1]:
continue
l, r = j + 1, len(nums) - 1
while l < r:
if nums[l] + nums[r] + nums[i] + nums[j] > target:
r -= 1
elif nums[l] + nums[r] + nums[i] + nums[j] < target:
l += 1
else:
res.append([nums[i], nums[j], nums[l], nums[r]])
lv, rv = nums[l], nums[r]
l += 1
r -= 1
while l < r and nums[l] == lv:
l += 1
while l < r and nums[r] == rv:
r -= 1
return res
454. 四数相加 II
https://leetcode-cn.com/problems/4sum-ii/
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。
例如:输入:A = [ 1, 2],B = [-2,-1],C = [-1, 2],D = [ 0, 2],输出:2,解释:两个元组如下:1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0,2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0。
思路
一:先两重循环遍历A、B,将和记录到字典rec中(键:和,值:和为该值的二元组的数目),两重循环遍历C、D,若字典中存在元素(component)能和他们的和为0,则又有rec[component]个数的元组。
from collections import defaultdict
class Solution(object):
def fourSumCount(self, A, B, C, D):
"""
:type A: List[int]
:type B: List[int]
:type C: List[int]
:type D: List[int]
:rtype: int
"""
n = len(A)
if n == 0:
return 0
rec = defaultdict(int)
for i in range(n):
for j in range(n):
rec[A[i] + B[j]] += 1
res = 0
for i in range(n):
for j in range(n):
component = 0 - C[i] - D[j]
if component in rec:
res += rec[component]
return res
280. 摆动排序
https://leetcode-cn.com/problems/wiggle-sort/submissions/
给你一个无序的数组 nums, 将该数字 原地 重排后使得 nums[0] <= nums[1] >= nums[2] <= nums[3]...。
示例:输入: nums = [3,5,2,1,6,4],输出: 一个可能的解答是 [3,5,1,6,2,4]
思路
一:将原数组非原址排序得到一个新的由小至大排好序的数组new_nums,把new_nums中的元素依次填入到nums的偶数位,再依次填入到奇数位即满足要求,时间复杂度O(nlgn),排序要O(nlgn)的时间复杂度,空间复杂度O(n)。例如nums = [3,5,2,1,6,4],则new_nums=[1, 2, 3, 4, 5, 6],第一轮填入后会改变nums偶数位的值,nums = [1,5,2,1,3,4],第二轮填入后会改变nums奇数位的值,nums=[1,4,2,5,3,6]。
class Solution(object):
def wiggleSort(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
new_nums = sorted(nums)
cur = 0
for i in range(0, len(nums), 2):
nums[i] = new_nums[cur]
cur += 1
for i in range(1, len(nums), 2):
nums[i] = new_nums[cur]
cur += 1
二:还是需要将原数组排序,不过可以原址排序,从第二个元素开始每两个元素交换一下位置,时间复杂度O(nlgn),排序要O(nlgn)的时间复杂度,空间复杂度O(1)。
[1, 2, 3, 4, 5, 6]
↑ ↑ ↑ ↑
swap swap
=> [1, 3, 2, 5, 4, 6]
class Solution(object):
def wiggleSort(self, nums):
nums.sort()
for i in range(1, len(nums) - 1 , 2):
nums[i], nums[i + 1] = nums[i + 1], nums[i]
三:转一个leetcode的官方解答,可以只用一遍完成任务。当我们遍历整个数组,比较当前元素与下一个元素。若顺序不正确,则交换之。https://leetcode-cn.com/problems/wiggle-sort/solution/bai-dong-pai-xu-by-leetcode/
class Solution(object):
def wiggleSort(self, nums):
less = True
for i in range(len(nums) - 1):
if less:
if nums[i] > nums[i + 1]:
nums[i], nums[i + 1] = nums[i + 1], nums[i]
else:
if nums[i] < nums[i + 1]:
nums[i], nums[i + 1] = nums[i + 1], nums[i]
less = not less
324. 摆动排序 II
https://leetcode-cn.com/problems/wiggle-sort-ii/
给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。
示例 1:输入: nums = [1, 5, 1, 1, 6, 4],输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
示例 2:输入: nums = [1, 3, 2, 2, 3, 1],输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2]
说明:你可以假设所有输入都会得到有效的结果。进阶:你能用 O(n) 时间复杂度和 / 或原地 O(1) 额外空间来实现吗?
思路
乍一看,与280摆动排序几乎一样,但是此题更加严格,必须严格大于或小于,不能等于,280的三种解法全不适用。该题的思路是转自leetcode上看到的题解https://leetcode-cn.com/problems/wiggle-sort-ii/solution/yi-bu-yi-bu-jiang-shi-jian-fu-za-du-cong-onlognjia/,怕以后找不到,自己copy了一段。
一:首先,我们可以很容易想到一种简单的解法:将数组进行排序,然后从中间位置进行等分(如果数组长度为奇数,则将中间的元素分到前面),然后将两个数组进行穿插。例如:对于数组[1, 5, 2, 4, 3],我们将其排序,得到[1, 2, 3, 4, 5],然后将其分割为[1, 2, 3]和[4, 5],对两个数组进行穿插,得到[1, 4, 2, 5, 3]。
但是这一解法有一个问题,例如,对于数组[1, 2, 2, 3],按照这种做法求得的结果仍为[1, 2, 2, 3]。如果题目不要求各元素严格大于或小于相邻元素,即,只要求nums[0] <= nums[1] >= nums[2] <= nums[3]...,那么这一解法是符合要求的,但题目要求元素相互严格大于或小于,那么需要稍微做一点改进。
为了方便阅读,我们在下文中定义较小的子数组为数组A,较大的子数组为数组B。显然,出现上述现象是因为nums中存在重复元素。实际上,由于穿插之后,相邻元素必来自不同子数组,所以A或B内部出现重复元素是不会出现上述现象的。所以,出现上述情况其实是因为数组A和数组B出现了相同元素,我们用r来表示这一元素。而且我们可以很容易发现,如果A和B都存在r,那么r一定是A的最大值,B的最小值,这意味着r一定出现在A的尾部,B的头部。其实,如果这一数字的个数较少,不会出现这一现象,只有当这一数字个数达到原数组元素总数的一半,才会在穿插后的出现在相邻位置。以下举几个例子进行形象地说明:例如,对于数组[1,1,2,2,3,3],分割为[1,1,2]和[2,3,3],虽然A和B都出现了2,但穿插后为[1,2,1,3,2,3],满足要求。
而如果2的个数再多一些,即[1,1,2,2,2,3],分割为[1,1,2]和[2,2,3],最终结果为[1,2,1,2,2,3],来自A的2和来自B的2出现在了相邻位置。出现这一问题是因为重复数在A和B中的位置决定的,因为r在A尾部,B头部,所以如果r个数太多(大于等于(length(nums) + 1)/2),就可能在穿插后相邻。要解决这一问题,我们需要使A的r和B的r在穿插后尽可能分开。一种可行的办法是将A和B反序:例如,对于数组[1,1,2,2,2,3],分割为[1,1,2]和[2,2,3],分别反序后得到[2, 1, 1]和[3, 2, 2],此时2在A头部,B尾部,穿插后就不会发生相邻了。当然,这只能解决r的个数等于(length(nums) + 1)/2的情况,如果r的个数大于(length(nums) + 1)/2,还是会出现相邻。但实际上,这种情况是不存在有效解的,也就是说,这种数组对于本题来说是非法的。此时我们得到了第一个解法,由于需要使用排序,所以时间复杂度为O(NlogN),由于需要存储A和B,所以空间复杂度为O(N)。
class Solution(object):
def wiggleSort(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
rec = sorted(nums)
n = len(rec)
# 将a、b反序,尽量避开重合元素
a = rec[0: (n - 1) // 2 + 1][::-1]
b = rec[(n - 1) // 2 + 1:][::-1]
for i in range(len(a)):
nums[i * 2] = a[i]
if i < len(b):
nums[i * 2 + 1] = b[i]
二:上一解法之所以时间复杂度为O(NlogN),是因为使用了排序。但回顾解法1,我们发现,我们实际上并不关心A和B内部的元素顺序,只需要满足A和B长度相同(或相差1),且A中的元素小于等于B中的元素,且r出现在A的头部和B的尾部即可。实际上,由于A和B长度相同(或相差1),所以r实际上是原数组的中位数。因此,我们第一步其实不需要进行排序,而只需要找到中位数即可。而寻找中位数可以用快速选择算法实现,时间复杂度为O(n)。加之需要满足A和B长度相同(或相差1)只能使用三路快排,保证中位数在中间且相邻,便于切分。
from random import randint
class Solution(object):
def wiggleSort(self, nums):
if len(nums) <= 1:
return
mid = (len(nums) - 1) // 2
self._quick_select(nums, 0, len(nums) - 1, mid)
a = nums[0: mid + 1][::-1]
b = nums[mid + 1:][::-1]
for i in range(len(a)):
nums[i * 2] = a[i]
if i < len(b):
nums[i * 2 + 1] = b[i]
def _quick_select(self, nums, l, r, mid):
if l >= r:
return
lt, gt = self._helper(nums, l, r)
if lt >= mid:
self._quick_select(nums, l, lt, mid)
elif gt <= mid:
self._quick_select(nums, gt, r, mid)
# [l,r]
def _helper(self, nums, l, r):
# randint(a, b) : Return random integer in range [a, b], including both end points
idx = randint(l, r)
self._swap(nums, l, idx)
val = nums[l]
# [l+1, lt] < val, (lt, i) == val, [gt, r] > val
lt, gt, i = l, r + 1, l + 1
while i < gt:
if nums[i] < val:
self._swap(nums, lt + 1, i)
i += 1
lt += 1
elif nums[i] == val:
i += 1
else:
self._swap(nums, gt - 1, i)
gt -= 1
# [l+1, lt - 1] < val, [lt, i) == val
self._swap(nums, lt, l)
lt -= 1
return lt, gt
def _swap(self, nums, i, j):
nums[i], nums[j] = nums[j], nums[i]
347. 前 K 个高频元素
https://leetcode-cn.com/problems/top-k-frequent-elements/
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:输入: nums = [1,1,1,2,2,3], k = 2,输出: [1,2]
示例 2:输入: nums = [1], k = 1,输出: [1]
说明:你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
思路
一:借助字典(键-元素值,值-元素频率),将字典按值排序。取前k个,时间复杂度O(nlgn)。
from collections import defaultdict
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
rec = defaultdict(int)
for i in range(len(nums)):
rec[nums[i]] += 1
rec = sorted(rec.items(), key=lambda a: a[1], reverse=True)
count, res = 0, []
for item in rec:
if count >= k:
break
res.append(item[0])
count += 1
return res
二:借助堆,时间复杂度O(nlgk)。
class Solution(object):
def topKFrequent(self, nums, k):
rec = collections.Counter(nums)
return heapq.nlargest(k, rec.keys(), rec.get)
977. 有序数组的平方
https://leetcode-cn.com/problems/squares-of-a-sorted-array/
给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
示例 1:输入:[-4,-1,0,3,10],输出:[0,1,9,16,100]
示例 2:输入:[-7,-3,2,3,11],输出:[4,9,9,49,121]
提示:1 <= A.length <= 10000,-10000 <= A[i] <= 10000,A 已按非递减顺序排序。
思路:
一:整体,绝对值排序后做平方,将A的小于0的元素乘以-1加入lt,大于等于零的加入gt,则lt由大到小排序,gt由小到大,将两个有序数组排序只需要O(n)的时间复杂度,排好序后再做平方,O(n)的时间复杂度,空间复杂度也是O(n)。
class Solution(object):
def sortedSquares(self, A):
"""
:type A: List[int]
:rtype: List[int]
"""
lt, gt = [], []
for item in A:
if item < 0:
lt.append(-1 * item)
else:
gt.append(item)
l, g, i = len(lt) - 1, 0, 0
a = [0] * len(A)
while l >= 0 or g < len(gt):
if l < 0:
a[i] = gt[g]
g += 1
elif g >= len(gt):
a[i] = lt[l]
l -= 1
elif lt[l] < gt[g]:
a[i] = lt[l]
l -= 1
else:
a[i] = gt[g]
g += 1
i += 1
for i in range(len(a)):
a[i] *= a[i]
return a
360. 有序转化数组
https://leetcode-cn.com/problems/sort-transformed-array/submissions/
给你一个已经 排好序 的整数数组 nums 和整数 a、b、c。对于数组中的每一个数 x,计算函数值 f(x) = ax2 + bx + c,请将函数值产生的数组返回。要注意,返回的这个数组必须按照 升序排列,并且我们所期望的解法时间复杂度为 O(n)。
示例 1:输入: nums = [-4,-2,2,4], a = 1, b = 3, c = 5,输出: [3,9,15,33]
示例 2:输入: nums = [-4,-2,2,4], a = -1, b = 3, c = 5,输出: [-23,-5,1,7]
思路
一:利用二次函数的特性,要么是单调的(退化成一次函数或者常数,全在二次函数对称轴的左侧或右侧),单调的在特判中处理了。剩下的就是非单调的,那么必定存在一个分界线,分界线的一边递增,另一边递减,递增的加入asc,递减的加入desc,得到两个有序数组,合并两个有序数组即是解。注意:数组中可能有重复的元素。
class Solution(object):
def sortTransformedArray(self, nums, a, b, c):
"""
:type nums: List[int]
:type a: int
:type b: int
:type c: int
:rtype: List[int]
"""
if not nums:
return nums
res = [a * item * item + b * item + c for item in nums]
# 特判
if len(res) == 1:
return res
if self._check_asc(res):
return res
res = res[::-1]
if self._check_asc(res):
return res
if a < 0:
# 先升后降
d_idx = 1
while d_idx < len(nums):
if res[d_idx] < res[d_idx - 1]:
break
d_idx += 1
asc, desc = res[:d_idx], res[d_idx:]
else:
# 先降后升
a_idx = 1
while a_idx < len(nums):
if res[a_idx] > res[a_idx - 1]:
break
a_idx += 1
asc, desc = res[a_idx:], res[:a_idx]
# 这边是将两个有序数组合并
i, a_idx, d_idx = 0, 0, len(desc) - 1
while i < len(res):
if a_idx >= len(asc):
res[i] = desc[d_idx]
d_idx -= 1
elif d_idx < 0:
res[i] = asc[a_idx]
a_idx += 1
elif asc[a_idx] < desc[d_idx]:
res[i] = asc[a_idx]
a_idx += 1
else:
res[i] = desc[d_idx]
d_idx -= 1
i += 1
return res
# 是递增序
def _check_asc(self, res):
for i in range(1, len(res)):
if res[i] < res[i - 1]:
return False
return True
986. 区间列表的交集
https://leetcode-cn.com/problems/interval-list-intersections/
给定两个由一些闭区间组成的列表,每个区间列表都是成对不相交的,并且已经排序。返回这两个区间列表的交集。(形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b。两个闭区间的交集是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3]。)
示例:
输入: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]],注意:输入和所需的输出都是区间对象组成的列表,而不是数组或列表。
提示:0 <= A.length < 1000,0 <= B.length < 1000,0 <= A[i].start, A[i].end, B[i].start, B[i].end < 10^9
思路
一:因为区间列表已经排好序,此题中若固定B列表中的区间,将A列表的区间的起始点与B中该区间的起始点对比,将A与B的相对位置的所有情况写出来,即是解。
class Solution(object):
def intervalIntersection(self, A, B):
"""
:type A: List[List[int]]
:type B: List[List[int]]
:rtype: List[List[int]]
"""
res = []
if not A or not B:
return res
i, j = 0, 0
while i < len(A) and j < len(B):
# A[i]终点在B[j]起点的左侧,没有交集
if A[i][1] < B[j][0]:
i += 1
# A[i]起点在B[j]起点的左侧,且A[i]终点在B[j]起点的右侧,必有交集,讨论终点
elif A[i][0] < B[j][0]:
end = min(A[i][1], B[j][1])
res.append([B[j][0], end])
# 讨论终点,看看哪个区间被用完要往后挪
if end == A[i][1]:
i += 1
if end == B[j][1]:
j += 1
# A[i]起点在B[j]起点的右侧,且A[i]终点在B[j]起点的右侧,讨论是否有交集
else:
# A[i]起点在B[j]终点的右侧,无交集
if A[i][0] > B[j][1]:
j += 1
# 讨论终点,看看哪个区间被用完要往后挪
else:
end = min(A[i][1], B[j][1])
res.append([A[i][0], end])
if end == A[i][1]:
i += 1
if end == B[j][1]:
j += 1
return res
二:从示例图以及方法一的代码中我们可以看出,无论是否有交集,A或B中都必定至少有一个指向下一个区间,我们可以对比A和B的终点决定谁要指向下一个区间,当然若存在交集,将交集添入res。
class Solution(object):
def intervalIntersection(self, A, B):
# 特判
if not A or not B:
return []
i, j, res = 0, 0, []
while i < len(A) and j < len(B):
low = max(A[i][0], B[j][0])
high = min(A[i][1], B[j][1])
# 存在交集
if low <= high:
res.append([low, high])
if A[i][1] < B[j][1]:
i += 1
else:
j += 1
return res
56. 合并区间
https://leetcode-cn.com/problems/merge-intervals/submissions/
给出一个区间的集合,请合并所有重叠的区间。
示例 1:输入: [[1,3],[2,6],[8,10],[15,18]],输出: [[1,6],[8,10],[15,18]],解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:输入: [[1,4],[4,5]],输出: [[1,5]],解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
思路
一:按起点排序,由前向后遍历,此时能否重合之需要比较终点是否大于等于待考察区间的起点,若是则可以合并,更新终点值;若不是,则不可以合并,将之前的区间加入res,并把该区间作为第一个区间继续考察下去。推出循环后要记住将最后一组low,high加入res。
通常遇到区间问题要对区间进行排序,常见的按起点排序或按终点排序,此处选择按起点排序,因为后面是由前向后遍历的,若按终点排序,则[[2,3],[4,5],[6,7],[8,9],[1,10]]会得出[[2,3],[4,5],[6,7],[1,10]]的结果,实际上应该是[[1,10]],第一个区间和第二个区间不重合,但是所有区间均在在最后一个区间表示的范围内,即若按终点排序,同时由前向后遍历,我们无法确定第一个遍历到的起点一定是真正的起点,但是按起点排序,由前向后遍历,则可以确定第一个区间的起点一定是起点,可以解决上述情况,此时第一个区间要么与别的可以合并但是起点是第一个区间的起点,若不能合并,起点显然也是第一个区间的起点。(若按终点排序,则应该由后向前遍历,比较起点与待考察区间终点的关系,此时也能保证由后向前的第一个区间的终点必定是终点)。
在确定可以合并时,区间的终点在待考察区间起点的右侧,取原先终点和待考察区间终点的最大值,若只取待考察区间的终点,则[[1,4],[2,3]]结果为[[1,3]],其实应为[[1,4]]
if high >= intervals_sort[i][0]:
high = max(high, intervals_sort[i][1])
class Solution(object):
def merge(self, intervals):
"""
:type intervals: List[List[int]]
:rtype: List[List[int]]
"""
if len(intervals) <= 1:
return intervals
intervals_sort = sorted(intervals, key=lambda a:a[0])
low, high, res = intervals_sort[0], []
for i in range(1, len(intervals_sort)):
if high >= intervals_sort[i][0]:
high = max(high, intervals_sort[i][1])
else:
res.append([low, high])
low, high = intervals_sort[i]
res.append([low, high])
return res