LeetCode合并两个升序数组:为何需复制结果到nums1?有何优化方案?
关于LeetCode「合并两个升序数组」的代码疑问解答
你的Java实现代码如下:
class Solution{ public static void merge(int[] nums1, int m, int[] nums2, int n) { int[] result = new int[m + n]; int i = 0, j = 0, k = 0; while (i < m && j < n) { if (nums1[i] < nums2[j]) { result[k++] = nums1[i++]; } else { result[k++] = nums2[j++]; } } while (i < m) { result[k++] = nums1[i++]; } while (j < n) { result[k++] = nums2[j++]; } System.arraycopy(result, 0, nums1, 0, m + n); } }
1. 为什么必须将result数组的内容复制到nums1中?
这是题目明确要求的:LeetCode该题规定合并后的升序数组必须存储在nums1里,而非返回新数组。题目给出的nums1数组长度本身就是m+n,已经预留了足够空间容纳所有合并后的元素,判题器会直接检查nums1的最终状态来判断答案是否正确。如果不把结果拷贝到nums1,判题器会认为你没有完成题目要求的输出目标。
2. 是否有更优的实现方案?
有,从后往前双指针法是更优的方案,它可以把空间复杂度从你的实现的O(m+n)降到O(1),不需要额外开辟result数组:
- 利用
nums1末尾的空闲位置(下标从m到m+n-1的区域),从两个数组的有效元素末尾开始比较 - 将较大的元素直接放到
nums1的当前最末尾位置,逐步往前填充 - 这样不会覆盖
nums1中还未处理的有效元素,完全原地操作
实现代码如下:
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int i = m - 1; // nums1有效元素的末尾下标 int j = n - 1; // nums2有效元素的末尾下标 int k = m + n - 1; // 合并后元素要放置的末尾下标 while (i >= 0 && j >= 0) { if (nums1[i] > nums2[j]) { nums1[k--] = nums1[i--]; } else { nums1[k--] = nums2[j--]; } } // 如果nums2还有剩余元素,直接拷贝到nums1的前面 while (j >= 0) { nums1[k--] = nums2[j--]; } } }
3. 直接打印result数组时出现超时问题是怎么回事?
LeetCode的判题环境对IO操作限制很严格,大量的打印输出会占用额外的IO资源。如果测试用例规模很大(比如m和n都是十万级别),打印数组的每个元素会导致IO耗时超过题目规定的时间限制,从而触发超时。另外,判题器根本不需要你打印结果,它只检查nums1的最终状态,所以提交代码时绝对不要加打印语句。
内容的提问来源于stack exchange,提问作者shivam0277
相关产品推荐
相关产品推荐

