目录
一:移除元素
给你一个数组
nums
和一个值val
,你需要 原地 移除所有数值等于val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用
O(1)
额外空间并 原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
思路:
使用快慢指针 !
定义两个变量,一个用来遍历数组查看是否有和val值相等的,一个用来记录下来不等于val值的,放入数组中;
//27移除元素
int removeElement(int* nums, int numsSize, int val)
{
int src = 0; //遍历 快指针
int dst = 0; //记录有效值 慢指针
//另外一种实现
//for (src; src < numsSize; ++src)
//{
// if (nums[src] != val)
// {
// nums[dst++] = nums[src];
// }
//}
while (src < numsSize)
{
if (nums[src] != val)
{
nums[dst++] = nums[src++]; //将有效值存到有效范围
}
else
{
src++;
}
}
return dst;
}
int main()
{
int nums[] = { 0, 1, 2, 2, 3, 0, 4, 2 };
int numsSize = sizeof(nums) / sizeof(nums[0]);
int val = 2;
int dst = removeElement(nums, numsSize, val);
printf("%d\n", dst); //vs调试写的,及以下可忽略
while (dst--)
{
printf("%d ", nums[dst]);
}
return 0;
}
时间复杂度:O(n),其中 n 为序列的长度。我们只需要遍历该序列至多两次。
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。
二:删除有序数组中的重复项
26. 删除有序数组中的重复项 - 力扣(LeetCode)
思路:
这里依旧可以使用快慢指针;
我这里还多定义了一个遍量,拿来记录有效值;不过显得冗余,但非常容易理解;
最后一步是将最后一个不同值记录下来;
从图可以看到dst走到最后一个元素时,此元素也应该记录;
int removeDuplicates(int* nums, int numsSize) {
int src = 1; //快指针
int dst = 0; //慢指针
int k = 0; //记录有效值
while (src < numsSize)
{
if (nums[src] != nums[dst])
{
nums[k++] = nums[dst++]; //将慢指针值放入有效范围中
src++;
}
else
{
src++;
dst++;
}
}
nums[k++] = nums[dst]; //将最后不同的值放入
return k;
}
刚刚也说了,可以对此想法进行优化
我们可以发现时删除重复项,也就说第一个元素该值都是有效的,可以定义变量从1开始;
然后定义遍历变量就行for循环,前后比较,将有效值放到有效位置中
int removeDuplicates(int* nums, int numsSize){
int index = 1; //第一个值默认有效
for(int i =1;i<numsSize;i++)
{
if(nums[i-1] != nums[i]) //前后比较
{
nums[index++] = nums[i]; //将快指针值放入有效位置中
}
}
return index;
}
三:合并两个有序数组
思路1:
题目说了 数组1是可以包容数组2进去的,我们可以直接将数组2有效值放入数组1最后一个有效值后,先将两个数组值合并在数组1中,再直接qsort排序即可啦
int compare(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
//合并两个数组
int j =m;
for(int i =0;i<n;i++)
{
nums1[j++] = nums2[i];
}
qsort(nums1,nums1Size,sizeof(nums1[0]),compare);
}
什么?你不知道qsort()
欧克,锁定往期文章【C语言】进阶------指针_敷敷_的博客-CSDN博客
里面详细讲述了关于 qsort()的使用哦,
思路2:
我们换一种方式,不使用qsort,
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
// end1、end2:分别标记nums1 和 nums2最后一个有效元素位置
// end标记nums1的末尾,因为nums1和nums2中的元素从后往前往nums1中存放
// ,否则会存在数据覆盖
int end1 = m - 1;
int end2 = n - 1;
int index = m + n - 1;
// 从后往前遍历,将num1或者nums2中较大的元素往num1中end位置搬移
// 直到将num1或者num2中有效元素全部搬移完
while (end1 >= 0 && end2 >= 0)
{
if (nums1[end1] > nums2[end2])
{
nums1[index--] = nums1[end1--];
}
else
{
nums1[index--] = nums2[end2--];
}
}
// num2中的元素可能没有搬移完,将剩余的元素继续往nums1中搬移
while (end2 >= 0)
{
nums1[index--] = nums2[end2--];
}
// num1中剩余元素没有搬移完 ---不用管了,因为num1中剩余的元素本来就在num1中
}