88. 合并两个有序数组(Merge Sorted Array)E
英文题目
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:
The number of elements initialized in nums1 and nums2 are m and n respectively.
You may assume that nums1 has enough space (size that is equal to m + n) to hold additional elements from nums2.
Example:
Input:
nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 Output: [1,2,2,3,5,6]
Constraints:
-10^9 <= nums1[i], nums2[i] <= 10^9
nums1.length == m + n
nums2.length == n
中文题目
给你两个有序整数数组 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]
提示:
-10^9 <= nums1[i], nums2[i] <= 10^9
nums1.length == m + n
nums2.length == n
暴力解法
把数组nums2放到nums2尾部,然后排序即可
时间复杂度O( (m+n)log(m+n) ),序列长度是m+n,直接套用快排的时间复杂度
空间复杂度O(log(m+n) )
# python3: 时间 32 ms, 击败 95.11%; 内存 14.9 MB, 击败 34.68% class Solution: def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ nums1[m:] = nums2 nums1.sort()
// c++: 时间 4 ms, 击败 53.83%; 内存 8.9 MB, 击败 24.28% class Solution { public: void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { for (int i = 0; i < n; ++i) { nums1[m+i] = nums2[i]; } sort(nums1.begin(), nums1.end()); } };
// java: 时间 1 ms, 击败 28.48%; 内存 40.3 MB, 击败 59.47% class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { for (int i = 0; i < n; ++i) { nums1[m+i] = nums2[i]; } Arrays.sort(nums1); } }
// go: 时间 0 ms, 击败 100%; 内存 2.2 MB, 击败 95.14% func merge(nums1 []int, m int, nums2 []int, n int) { copy(nums1[m:], nums2) sort.Ints(nums1) }
// javascript: 时间 60 ms, 击败 74.88%; 内存 41.3 MB, 击败 21.41% /** * @param {number[]} nums1 * @param {number} m * @param {number[]} nums2 * @param {number} n * @return {void} Do not return anything, modify nums1 in-place instead. */ var merge = function(nums1, m, nums2, n) { nums1.splice(m, nums1.length - m, ...nums2); nums1.sort((a,b) => a-b); };
双指针
新开辟一个数组,排序后替换nums1
时间复杂度O(m+n),空间复杂度O(m+n)
# python3: 时间 36 ms, 击败 84.02%; 内存 14.8 MB, 击败 77.58% class Solution: def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ merged = [] p1, p2 = 0, 0 while p1 < m and p2 < n: if nums1[p1] <= nums2[p2]: merged.append(nums1[p1]) p1 += 1 else: merged.append(nums2[p2]) p2 += 1 merged.extend(nums1[p1:m]) merged.extend(nums2[p2:]) nums1[:] = merged
// c++: 时间 4 ms, 击败 53.83%; 内存 9 MB, 击败 11.19% class Solution { public: void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { vector<int> merged; int p1 = 0, p2 = 0; while (p1 < m && p2 < n) { if (nums1[p1] <= nums2[p2]) { merged.push_back(nums1[p1]); ++p1; } else { merged.push_back(nums2[p2]); ++p2; } } merged.insert(merged.end(), nums1.begin()+p1, nums1.begin()+m); merged.insert(merged.end(), nums2.begin()+p2, nums2.end()); nums1 = merged; } };
// java: 时间 0 ms, 击败 100%; 内存 39.9 MB, 击败 97.88% class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int[] merged = new int[m+n]; int p1 = 0, p2 = 0; int cur = 0; while (p1 < m && p2 < n) { if (nums1[p1] < nums2[p2]) { cur = nums1[p1]; ++p1; } else { cur = nums2[p2]; ++p2; } merged[p1+p2-1] = cur; } while (p1 < m) { merged[p1+p2] = nums1[p1]; ++p1; } while (p2 < n) { merged[p1+p2] = nums2[p2]; ++p2; } for (int i = 0; i < merged.length; ++i) { nums1[i] = merged[i]; } } }
// go: 时间 0 ms, 击败 100%; 内存 2.2 MB, 击败 17.24% func merge(nums1 []int, m int, nums2 []int, n int) { merged := make([]int, 0, m+n) p1, p2 := 0, 0 for p1 < m && p2 < n { if (nums1[p1] < nums2[p2]) { merged = append(merged, nums1[p1]) p1++ } else { merged = append(merged, nums2[p2]) p2++ } } merged = append(merged, nums1[p1:m]...) merged = append(merged, nums2[p2:]...) copy(nums1, merged) }
// javascript: 时间 56 ms, 击败 89.79%; 内存 41.3 MB, 击败 16.29% /** * @param {number[]} nums1 * @param {number} m * @param {number[]} nums2 * @param {number} n * @return {void} Do not return anything, modify nums1 in-place instead. */ var merge = function(nums1, m, nums2, n) { let merged = new Array(); let p1 = 0, p2 = 0; while (p1 < m && p2 < n) { if (nums1[p1] < nums2[p2]) { merged.push(nums1[p1]); ++p1; } else { merged.push(nums2[p2]); ++p2; } } merged = merged.concat(nums1.slice(p1, m)); merged = merged.concat(nums2.slice(p2, n)); for (let i = 0; i < m+n; ++i) { nums1[i] = merged[i]; } };
逆向双指针
从后往前遍历即可
时间复杂度O(m+n),空间复杂度O(1)
# python3: 时间 36 ms, 击败 85.59%; 内存 16.1 MB, 击败 41.38% class Solution: def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ p1, p2 = m-1, n-1 cur = m + n - 1 while p1 >= 0 and p2 >= 0: if nums1[p1] > nums2[p2]: nums1[cur] = nums1[p1] p1 -= 1 else: nums1[cur] = nums2[p2] p2 -= 1 cur -= 1 # 此处只需要判断nums2即可,不需要判断nums1 # 原因是,如nums2已走完,nums1必然有序 while p2 >= 0: nums1[cur] = nums2[p2] p2 -= 1 cur -= 1
// c++: 时间 4 ms, 击败 53.83%; 内存 8.8 MB, 击败 71.38% class Solution { public: void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { int p1 = m-1, p2 = n-1; int cur = m+n-1; while (p1 >= 0 && p2 >= 0) { if (nums1[p1] > nums2[p2]) { nums1[cur] = nums1[p1]; --p1; } else { nums1[cur] = nums2[p2]; --p2; } --cur; } while (p2 >= 0) { nums1[cur] = nums2[p2]; --p2; --cur; } } };
// java: 时间 0 ms, 击败 100%; 内存 40.2 MB, 击败 74.88% class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int p1 = m-1, p2 = n-1; int cur = m+n-1; while (p1 >= 0 && p2 >= 0) { if (nums1[p1] > nums2[p2]) { nums1[cur] = nums1[p1]; --p1; } else { nums1[cur] = nums2[p2]; --p2; } --cur; } while (p2 >= 0) { nums1[cur] = nums2[p2]; --p2; --cur; } } }
// go: 时间 0 ms, 击败 100%; 内存 2.2 MB, 击败 89.20% func merge(nums1 []int, m int, nums2 []int, n int) { p1, p2 := m-1, n-1 cur := m+n-1 for p1 >= 0 && p2 >= 0 { if nums1[p1] > nums2[p2] { nums1[cur] = nums1[p1] p1-- } else { nums1[cur] = nums2[p2] p2-- } cur-- } for p2 >= 0 { nums1[cur] = nums2[p2] p2-- cur-- } }
// javascript: 时间 60 ms, 击败 74.88%; 内存 41.1 MB, 击败 63.19% /** * @param {number[]} nums1 * @param {number} m * @param {number[]} nums2 * @param {number} n * @return {void} Do not return anything, modify nums1 in-place instead. */ var merge = function(nums1, m, nums2, n) { let p1 = m-1, p2 = n-1; let cur = m+n-1; while (p1 >= 0 && p2 >= 0) { if (nums1[p1] > nums2[p2]) { nums1[cur] = nums1[p1]; --p1; } else { nums1[cur] = nums2[p2]; --p2; } --cur; } while (p2 >= 0) { nums1[cur] = nums2[p2]; --p2; --cur; } };
也可两个循环合并在一起,但个人感觉上面的写法更易懂,写法如下:
# python3: 时间 32 ms, 击败 95.11%; 内存 14.8 MB, 击败 86.42% class Solution: def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ p1, p2 = m - 1, n - 1 # cur为nums1排序后的索引下标 for cur in range(m + n - 1, -1, -1): # 此处可进行优化,原因是,当nums2已走完 # 此时nums1必然已经有序,可直接返回 if p2 == -1: return elif p1 == -1 or nums1[p1] < nums2[p2]: nums1[cur] = nums2[p2] p2 -= 1 else: # nums1[p1] >= nums2[p2]: nums1[cur] = nums1[p1] p1 -= 1
// c++: 时间 4 ms, 击败 64.59%; 内存 8.6 MB, 击败 99.87% class Solution { public: void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { int p1 = m-1, p2 = n-1; for (int cur = m+n-1; cur >= 0; --cur) { if (p2 == -1) { return; } else if (p1 == -1 || nums1[p1] <= nums2[p2]) { nums1[cur] = nums2[p2]; --p2; } else { nums1[cur] = nums1[p1]; --p1; } } } };