经典题目:移除重复元素
1.原地删除值=val的元素
题目描述:
点击跳转到Leetcode----移除元素
如果不考虑空间复杂度,可以用拷贝新数组的方法:
用src指针挨个遍历数组元素,如果数组元素不等于val,就把下标为src的元素拷贝到新数组中,然后为了储存下一个不等于val的数,新数组中的dst++。最后把弄好的新数组拷贝回去,毕竟是要改变原来的数组。
拷贝结束的新数组中,dst的下标就是新数组的长度。
动态图示:
但这种方法的空间效率比较低,需要开辟新的空间,空间复杂度为O(N),不符合这道题的要求。
开辟新数组的方法实质上是通过指针异地拷贝,既然可以异地拷贝,那么大概率也可以原地拷贝,换汤不换药,原地拷贝的思路是一样的。、
原地拷贝:
动态图示:
类比上面新数组的方法,用src指针挨个遍历数组元素,如果数组元素不等于val,就把下标为src的元素拷贝到下标为dst的位置上,然后为了存下一个不等于val的数,dst++
优化后的空间复杂度为O(1),时间复杂度为O(N)。
代码:
int removeElement(int* nums,int numsSize,int val){
int src=0;
int dst=0;
while(src < numSize){
if(nums[src]!=val){
nums[dst++] = nums[src++];
}
else
{
src++;
}
}
return dst;
}
2.删除有序数组中的重复项
题目描述
点击跳转到Leetcode----删除有序数组中的重复项
类似的,只不过这道题的比较标准不是固定的一个"val"而是一个变化的数了,初始位置src在下标1,dst在下标0,初始时将两个指针指向的位置错开,才能保证src和dst能前后比较。
新数组的长度是dst+1。
动态图示:
代码:
int removeDuplicates(int* nums, int numsSize){ int src=1; int dst=0; while(src < numsSize){ if(nums[src] != nums[dst]){ nums[++dst]=nums[src]; } src++; } return dst+1; }
总结
以上题目的算法可以说是由开辟新数组的算法优化来的,我们由开辟新数组的过程优化出了空间复杂度更低的算法,通过了题目。
如果一开始碍于题目的种种限制,比如空间复杂度、时间复杂度等要求,而一时想不出来思路,可以先忽视题目要求,使用常规的、普通的方法解题,然后进行类比,或许就能开发出效率更高的且符合题目要求的算法。
本文结束。
(如果文章有错误之处,请在评论区点醒作者,谢谢!)