905. 按奇偶排序数组
解题思路:
-
1)额外数组 + 两次遍历,第一遍将所有的 偶数 放到结果数组 res 的前面,第二遍将所有的 奇数 接着放到结果数组 res 的后面。也可以使用 对撞指针 往结果数组里存,在 一次遍历 内搞定。
-
2) 对撞指针 , 从 左边 不断的找到 第一个 奇数 , 从 右边 不断的找到第一个 偶数 ,找到就交换 左边 和 右边 。不断重复以上过程。原地算法,空间O(1)。
解题思路:
- 3)快排二路分区逻辑,参考快排中分区交换的逻辑来处理,快排分区逻辑中是将比分区点小的交换到左边,将比分区点大的交换到右边,而本题可以认为是按奇偶性进行排序,将偶数交换到左边,将奇数交换到右边。
快排二路分区逻辑有两种版本,一种是使用对撞指针的版本,另一种是使用快慢指针的版本。
对撞指针的二路分区版本:
这个版本其实跟上面的方法 2)本质上是一样的。
快慢指针的二路分区版本:
这个版本只能算是快排二路分区快慢指针版本的变形,并不是严格的分区逻辑。
注意:本题与 [
剑指 Offer 21.调整数组顺序使奇数位于偶数前面
] 几乎雷同。
922. 按奇偶排序数组 II
解题思路:
-
1) 额外数组 + 遍历原数组 ,将 偶数 放到新数组的偶数下标位置上 i = 0,i += 2 ,将 奇数 放到新数组的奇数下标位置 上 j = 1,j += 2。
-
2 ) 双指针 + 原地处理, i 指向偶数下标 i = 0 , j 指向奇数下标 j = 1 ,遍历数组的每一个 偶数位 , i += 2 ,如果在 偶数位 上发现一个 奇数 时,就不停的 while 尝试在 奇数位 上找到一个 偶数 , j += 2 ,如果找到就交换二者swap(i, j)。
注意 i 和 j 的步长都要 + 2,因为奇偶下标都是间隔的。
88. 合并两个有序数组
解题思路:
-
1) 额外数组,参考 归并排序 中合并两个有序数组的过程,设指针 i 和 j 分别指向 nums1 和 nums2 ,然后比较二者 较小 的值存到 tmp 数组中,最后再将 tmp 数组拷贝到原数组。 空间O( m+n ) 时间 O(m+n)
不过题目中 nums1 预留了额外空间,很显然是要原地修改,而不是使用额外空间。
解题思路:
-
2) 三指针逆向存取 ,设 i、 j、k 分别指向 nums1、 nums2、结果数组 的末尾, 遍历时从 nums1 和 nums2 屁股后面开始取值,谁 大 就把谁安排到 结果数组 的屁股后面(本题 结果数组 就是 nums1 )。 然后分别把较大的指针和结果数组的指针 前移 一个。
-
如果有一个取到空了,就把另一个剩余的全部逆序放入 nums1 中。
-
循环条件是 nums1 和 nums2 的指针有一个没到头就继续 。
当 nums1==nums2[j] 时,代码中取谁都无所谓,不会影响最终结果。
56. 合并区间
解题思路:
-
按照区间左端点升序排序 ,然后遍历所有的区间,依次比较 当前区间 与合并 结果集合 中的 前一个区间 是否有重叠,如果无重叠就直接把当前区间收集到结果集合中,如果有重叠就把当前区间合并到前一个区间中。
-
判断 当前区间 与 前一个区间 是否有重叠的方法:
-
前一个区间 的 右端点 < 当前区间 的 左端点 ,则 无重叠 , 前一个区间 的 右端点 > = 当前区间 的 左端点 ,则有重叠 。 例如考虑左端点两个升序排列的两个区间 [a, b] [c, d] : 若 b < c 则无交集,若 b >= c 则有交集,如果有交集,则 交集的左边界 = a, 交集的 右边界 = max(b, d)
57. 插入区间
解题思路:
-
1)观察 插入区间 和 原始区间 左右边界的关系 ,可得 不重叠 的条件是: 原区间.右 < 插入区间.左 或 原区间.左 > 插入区间.右 。
-
先分别找出 重叠开始 和 结束 的区间索引,当然,也有可能插入的区间与所有原始区间都没有重叠(此时找不到重叠开始和结束的区间索引,记为-1)。
-
我们可以分成以下两大类情况处理:
-
① 插入区间与原始区间 有重叠 的情况,我们需要 合并重叠 的区域,然后按照 重叠之前、合并、重叠之后 的顺序添加区间。
-
② 插入区间与原始区间 无重叠 的情况,就先直接添加 原始所有区间 ,并记录应该插入新区间的位置,最后再插入新区间即可。
这里如果 start == -1,则 end 一定也等于 -1,如果 start != -1,则 end 也一定不等于 -1,所以只需要是否重叠判断 start 是否为 -1 即可。
另外在无重叠情况下,查找插入位置,其实就是在一个有序数组中查找第一个比插入目标大的位置(因为题目给定的区间是已经按照左端点升序排序好了的),例如 1,2,3,7,9 中插入 5 我们应该找到 7 的位置,将 5 插入该位置,原来的 7 和 9 分别后移。
解题思路:
- 2)分成三个阶段来考察
- ① 先将 区间右边界 < 插入区间左边界 的区间放入到结果集,这些区间与插入区间无重叠
- ② 将 区间左边界 ≤ 插入区间右边界 && 区间右边界 ≥ 插入区间左边界 的区间和插入区间进行合并,然后把合并的区间放入到结果集
- ③ 将剩余的区间放入结果集,这些区间与插入区间无重叠
252. 会议室
解题思路:
-
同56,只需要 判断区间是否有重叠 的即可,一旦有重叠的两个会议时间段,就不能全部参加了。
-
先 按照区间左端点升序排序 ,然后遍历所有的区间, 比较 [a, b] [c, d] 中是否有 b > c 的情况, 即 前一个会议 的 结束时间 大于 当前会议 的 开始时间 ,那么就冲突了。
-
注意:本题中 b == c 是允许的,因为在前一个会议恰好结束时开始下一个会议是可以的。
253. 会议室 II
解题思路:
-
1. 转化为公交车上下车问题 ,某个时刻上车 +1 人,某个时刻下车 -1 人,求车上最多有几人。题目要求的其实就是可在同一时刻进行的会议的最大数量。
-
首先按照 [a, b] -> [[a, 1], [b, -1]]