使用双指针解LeetCode合并数组问题:for循环i=0后不递减?
问题分析与解决思路
你的代码并非i不再递减,而是触发了数组越界异常导致程序提前终止。问题出在条件判断的逻辑上:当ptr1变为-1(nums1的有效元素已全部处理完毕)时,你仍会执行nums1[ptr1]的访问操作,这在Java中会直接抛出ArrayIndexOutOfBoundsException,程序崩溃后自然无法继续执行后续循环。
核心问题点
原条件if(ptr2 < 0 || nums1[ptr1] > nums2[ptr2])存在逻辑漏洞:当ptr1 < 0但ptr2 >=0时,会先执行nums1[ptr1]的访问,直接触发越界异常。
修正方案
调整判断逻辑的优先级,先确保ptr1的合法性,再进行元素比较:
- 优先判断
ptr1是否还有未处理的元素,同时结合ptr2的状态和元素大小关系 - 当
ptr1已耗尽(<0),直接取nums2的剩余元素;当ptr2已耗尽,直接取nums1的剩余元素
修正后的代码
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int ptr1 = m - 1, ptr2 = n - 1; // 从nums1的末尾开始填充 for(int i = m + n - 1; i >= 0; i--) { if (ptr1 >= 0 && (ptr2 < 0 || nums1[ptr1] > nums2[ptr2])) { // ptr1还有元素,且要么ptr2已耗尽,要么当前nums1元素更大 nums1[i] = nums1[ptr1--]; } else { // 要么ptr1已耗尽,要么nums2元素更大,取nums2的元素 nums1[i] = nums2[ptr2--]; } } } }
额外优化说明
可以在循环中提前终止:当ptr2 < 0时,nums2的元素已全部处理完毕,nums1剩余的前m个元素本来就是有序的,无需继续循环,能减少不必要的迭代:
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int ptr1 = m - 1, ptr2 = n - 1; int i = m + n - 1; while (ptr2 >= 0) { if (ptr1 >= 0 && nums1[ptr1] > nums2[ptr2]) { nums1[i--] = nums1[ptr1--]; } else { nums1[i--] = nums2[ptr2--]; } } } }
这种写法更高效,因为当nums2的元素全部合并完成后,剩下的nums1前半部分已经是有序状态,不需要再处理。
内容的提问来源于stack exchange,提问作者JediMasta
相关产品推荐
相关产品推荐

