合并有序数组
题目地址: https://leetcode-cn.com/problems/merge-sorted-array/
| 12
 3
 4
 5
 6
 7
 8
 
 | 题目:给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
 说明:
 初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
 示例:
 输入:nums1 = [1,2,3,0,0,0], m = 3、nums2 = [2,5,6], n = 3
 输出:[1,2,2,3,5,6]
 
 | 
解法一:暴力美学(追加+排序)
将nums2 中前n个元素 追加到 nums1 m位置
然后将 前面 m + n 个元素排序
| 12
 3
 4
 5
 6
 7
 8
 
 | public void merge(int[] nums1, int m, int[] nums2, int n) {for (int i = 0; i < n; i++) {
 nums1[m++] = nums2[i];
 }
 
 
 Arrays.sort(nums1, 0, m);
 }
 
 | 
时间复杂度 : O((n+m)log(n+m))。
空间复杂度 : O(1)。
解法二:多指针(从前到后)
创建一个新数组temp,比较temp 和 nums2 中元素,因为两个数组是有序的,所以按照顺序,择二者中较小的元素放置到 nums1 中
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | public void merge(int[] nums1, int m, int[] nums2, int n) {
 int[] temp = new int[m];
 System.arraycopy(nums1, 0, temp, 0, m);
 int num1_i = 0;
 int temp_i = 0;
 int num2_i = 0;
 while (num1_i < m + n) {
 
 if (num2_i >= n) {
 nums1[num1_i++] = temp[temp_i++];
 } else if (temp_i >= m) {
 
 nums1[num1_i++] = nums2[num2_i++];
 } else {
 
 nums1[num1_i++] = temp[temp_i] < nums2[num2_i] ? temp[temp_i++] : nums2[num2_i++];
 }
 }
 }
 
 | 
时间复杂度 : O(n+m)。
空间复杂度 : O(m)。
解法三:多指针(从后到前)
由于题目中不考虑nums1 中后面的元素,所以采用覆盖的操作,将 nums1 中m位置后面的元素从大到小依次从后到前设置到nums1 中即可完成合并
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | public void merge2(int[] nums1, int m, int[] nums2, int n) {
 
 int last = m-- + n-- - 1;
 while (n >= 0) {
 
 
 nums1[last--] = m < 0 ? nums2[n--] : nums2[n] > nums1[m] ? nums2[n--] : nums1[m--];
 }
 }
 
 | 
时间复杂度 : O(n+m)。
空间复杂度 : O(1)。
合并有序链表
题目地址:https://leetcode-cn.com/problems/merge-two-sorted-lists/
| 12
 3
 4
 5
 
 | 题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
 示例:
 输入:1->2->4, 1->3->4
 输出:1->1->2->3->4->4
 
 | 
ListNode 类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | public class ListNode {int val;
 ListNode next;
 ListNode() {}
 ListNode(int val) {
 this.val = val;
 }
 ListNode(int val, ListNode next) {
 this.val = val; this.next = next;
 }
 }
 
 | 
解法一:多指针
思路:定义一个头节点 temp,然后依次比较 l1、l2 的头节点,选择较小的一个作为 temp 的next节点(temp = l1 < l2 ? l1 : l2)。最后将非null的 节点追加到 baseNode后面,因为最后是要返回整个链,所以需要前面再定义一个临时节点 baseNode 指向temp 的头节点。最终返回 baseNode的next 对应的链。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | public static ListNode mergeTwoLists2(ListNode l1, ListNode l2) {if (l1 == null || l2 == null) {
 return l1 == null ? l2 : l1;
 }
 ListNode baseNode = new ListNode(0);
 ListNode temp = baseNode;
 while (l1 != null && l2 != null) {
 if (l1.val < l2.val) {
 temp.next = l1;
 l1 = l1.next;
 } else {
 temp.next = l2;
 l2 = l2.next;
 }
 temp = temp.next;
 }
 temp.next = l1 == null ? l2 : l1;
 return baseNode.next;
 }
 
 | 
空间复杂度:O(m + n)
时间复杂度:O(1)
解法二:递归
思路:比较 l1 和 l2 , 如果 l1 < l2 ,再通过l1.next 和 l2 比较,直至递归调用完成
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {if (l1 == null || l2 == null) {
 return l2 == null ? l1 : l2;
 }
 if (l1.val < l2.val) {
 l1.next = mergeTwoLists(l1.next, l2);
 return l1;
 } else {
 l2.next = mergeTwoLists(l1, l2.next);
 return l2;
 }
 }
 
 | 
时间复杂度:O(n+m)
空间复杂度:O(n+m)