顺序表算法题(LeetCode)
1 移除元素
代码示例:
int removeElement(int* nums, int numsSize, int val) {int left = 0;for( int right = 0;right<numsSize;right++){if(nums[right]!=val){nums[left++]=nums[right];}}return left;
}
代码详细说明:
我们定义了两个变量left
和right
,left
作为标定位表示在它前面的元素都不为val
,right
则作为判断位一直向后面找不为val
的元素
建立一个for
循环让right
一直走到数组最后一个位置
for( int right = 0;right<numsSize;right++);
如果right
指向的数组元素不等于val
则让right
指向数组元素赋值给left
指向的下标,如果等于val
则不做任何处理
if(nums[right]!=val){nums[left++]=nums[right];}}
最后left
则为不等于val
的数组元素数,将其返回
return left;
小结:本题采用两个指针(不是C语言的指针,表示指向数组位置的意思)
left
,right
。right
指针负责遍历,而left
指针确定要修改的位置,如果遇到数组元素一直不为val
,则两者一起移动,如果遇到val
则left
停下来,直到right
指针找到不为val
的值将其赋值给left
指针位置。
2 删除有序数组中的重复项
代码示例:
int removeDuplicates(int* nums, int numsSize) {int left ,right;left = 0;right = left+1;while(right<numsSize){if(nums[left]!=nums[right]){left++;nums[left]=nums[right]; }right++;}return left+1;
}
代码详细说明:
本题数组是一个非严格递增函数(即前面元素<=后面元素),面对这个数组删除重复项,依旧是采用两个指针left
,right
。left
指针由于锁定位置要改变的位置,而right
则向后遍历找不等于left
指向的元素与其交换。
首先,让left
指向第一个元素下标,right
指向left
后面的一个位置,right=left+1
。
left = 0;
right = left+1;
right
指针直到最后一个数组元素后面时则循环结束
while(right<numsSize)
在循环体中如果left
指针指向内容与right
相同时则只right
指针移动,只有当left
指向数组元素大小与right
时left
指针才会向后一位并将right
指向内存赋值给left
指针指向区域。
if(nums[left]!=nums[right]){left++;nums[left]=nums[right]; }right++;}
由于left
是数组下标,所以返回实际元素个数时需要+1
return left+1;
最后说明:题目对数组元素大小限制非空,所以不存在数组元素大小为
0
的情况。
3 合并两个有序数组
代码示例:
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int s1_right = m+n-1;int s1_left = m-1;int s2_right = n-1;while(s1_left>=0&&s2_right>=0){if(nums2[s2_right]>=nums1[s1_left]){nums1[s1_right]=nums2[s2_right];s2_right--;}else{nums1[s1_right]=nums1[s1_left];s1_left--;}s1_right--;}//当有剩余的数组时while(s2_right>=0){nums1[s1_right]=nums2[s2_right];s1_right--;s2_right--; }
}
代码总体思路:由于两个数组元素都是非递减序列,并且我们最后也要保证改变后的
nums1
也是非递减序列,所以我们可以从nums1
的最后一个位置开始赋值元素,即从后往前改变nums1
数组,这样的设计也不会改变nums1
的前面元素。我们取出从后往前取出nums1
和nums2
的元素并比较大小将大的往nums1
后面放。直到一个数组的元素全部放完,如果放完的是nums1
则直接将剩下的nums2
元素依次赋值到nums1
前面就行了,如果是nums2
放完则不用改变什么。
代码详细讲解:
创建三个指针分别指向
int s1_right = m+n-1;int s1_left = m-1;int s2_right = n-1;
当其中一个数组元素被遍历完之后则跳出循环
while(s1_left>=0&&s2_right>=0)
在循环体里面nums1
和nums2
后面元素比较大小,并将较大值赋值给nums1[s1_right]
,并更新指针指向。
if(nums2[s2_right]>=nums1[s1_left]){nums1[s1_right]=nums2[s2_right];s2_right--;}else{nums1[s1_right]=nums1[s1_left];s1_left--;}s1_right--;
当其中一个数组遍历完成时,如果是nums1
被遍历完则直接将nums2
剩余元素全部放到nums1
数组中
while(s2_right>=0){nums1[s1_right]=nums2[s2_right];s1_right--;s2_right--; }
由于题目设计
nums1
的数组大小是正好装的下两个数组全部元素的,所以在添加nums2
元素到nums1
中是不会覆盖和改变nums1
元素的,除非当前位置nums1
元素已经被拿到s1_right
指针处赋值过了。