移除数组:
题目链接:力扣(LeetCode)
原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。
这道题如果不考虑时间、空间复杂度,有三种解法:
1.暴力求解法:
直接将所有数组元素遍历一遍,一一与val的值相比较,如果相等,就用后面的数组元素挪动覆盖该元素。
但是这种方法的时间复杂度:O(N^2),不符合题目要求。
2. 空间换时间:
开辟一个新的数组tmp,将原数组中数组元素与val的值相比较,如果相等,src++,如果不相等,就把该元素放到新数组tmp中,并且src++、dst++,最后把新数组中的内容放回到原数组即可。
这种方法的时间复杂度:O(N),空间复杂度:O(N)。
以上两种方法都不是很完美,因此我们不详细讲解代码,下面我们讲一种完美的解决方案:
3.双指针解法:
实际上这种方法和上述空间换时间的方法原理相同,只不过我们不用新开辟一个数组。
首先,将src和dst指在原数组的初始位置,然后将下标为src的元素与val的值相比较,如果相等,src++,如果不相等,把下标为src的数组元素赋给下标为dst的数组元素,并且src++、dst++,直到找完所有数组元素。
这就是直接在原数组上操作。 下面给出代码:
int removeElement(int* nums, int numsSize, int val) { int str=0; int dst=0; while(str<numsSize) { if(nums[str]!=val) { nums[dst++]=nums[str++]; } else { str++; } } return dst; }
删除排序数组中的重复项:
题目链接:力扣(LeetCode)
删除排序数组中的重复项。
这道题也是使用双指针,src指向下标为1处,dst指向下标为0处,当下标为src不等于下标为dst的元素时,先将dst++,然后将下标为src的元素赋给下标为dst的元素,再将src++,依次往后,直到找完所有的数组元素。
下面给出代码:
int removeDuplicates(int* nums, int numsSize) { int src=1; int dst=0; while(src<numsSize) { if(nums[src]!=nums[dst]) { dst++; nums[dst]=nums[src]; src++; } else { src++; } } return dst+1; }
合并两个有序数组:
题目链接:力扣(LeetCode)
合并两个有序数组。
要解这道题就要用三指针的方法,为了避免数据发生覆盖,我们采用从后往前的方式,找到两个数组要合并的最后面的元素,定义下标end1等于m-1,下标end2等于n-1,下标dst=m+n-1,然后把end1和end2代表的元素相比较,如果end1>end2,把end1的数据拷贝到dst,然后end1--,dst--;如果end2>end1,把end2的数据拷贝到dst,然后end2--,dst--,依次往前,直到其中一个数组中的数据先拷贝完毕,结束循环。
注意:题目要求是把所有的元素拷贝到nums1数组中,所以如果拷贝的时候nums2数组先结束,就不用再拷贝。但如果是nums1数组先拷贝结束,那说明nums2数组中的元素可能还没有完全拷贝到nums1中,所以应该再写个循环,将muns2中剩下的元素拷贝到nums1中,这才真正实现了合并。
下面给出代码:
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) { int end1=m-1; int end2=n-1; int dst=m+n-1; while(end2 >= 0&&end1>=0) { if(nums1[end1]>nums2[end2]) { nums1[dst--]=nums1[end1--]; } else { nums1[dst--]=nums2[end2--]; } } while(end2>=0) { nums1[dst--]=nums2[end2--]; } }