这篇我将从力扣的三个题目入手,来加深对顺序表的作用的关注。
1.移除元素
题目链接:https://leetcode.cn/problems/remove-element/description
思路:双指针法,第一个变量src指向原位置的下标,dst变量指向移位后的下标,即为src在这里一直遍历完整个数组,然后我们需要一直赋值,nums[dst]=nums[src],dst在遇到与k相同的元素时就不会++,这样就可以使这个数一直赋值给这个前面的位置,理解了思路就开始敲代码了:
int removeElement(int* nums, int numsSize, int val)
{
int dst = 0;
int src = 0;
while (src < numsSize)
{
if (nums[src] != val)
{
nums[dst] = nums[src];
dst++;
}
src++;
}
return dst;
//这个不能为dst+1,我们可以认为nums[dst]是没有赋值的位置
}
提交代码后发现没有问题,如果我们按照常规思考,我们都想是用两个循环来依次移动数组元素,如我所写:
int removeElement(int* nums, int numsSize, int val)
{
int i, j, k = 0;
for (i = 0; i < numsSize; i++)
{
if (nums[i] == val)
{
k++;
for (j = i; j < --numsSize; j++)
{
nums[j] = nums[j + 1];
}
}
}
return numsSize;
}
这个代码时间复杂度为O(n^2),不好的解法。
2.删除有序数组中的重复项
题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description
思路:查找重复数据,然后把重复数据覆盖,我们和上一题解决方法可以相同,但是要改一下,我们需要dst指向初始位置,然后src指向dst指向的下一个位置,然后看是否相等,如果相等,我们需要把src++,dst不变,最终返回的是dst+1,如果不相等,则两者都加1.思路分析完了,我们开始写代码吧:
int removeDuplicates(int* nums, int numsSize)
{
int dst = 0;
int src = 1;
while (src <= numsSize)
{
if (nums[dst] == nums[src])
{
src++;
}
else
{
dst++;
nums[dst] = nums[src];
//不能先赋值再+1,不然会把之前位置的值给覆盖掉,最终结果会少一个值
//这题不像之前的题目,之前的题目是等待赋值,而这个题目是要先比较再看是否要赋值
src++;
}
}
return dst + 1;
}
但是发现报错了,我们要考虑是否出现数组越界的情况,所以我们需要把循环条件改为src int removeDuplicates(int* nums, int numsSize) 3.合并两个有序数组 题目链接:https://leetcode.cn/problems/merge-sorted-array/description/ 思路1:先合并两个数组,再进行冒泡排序,这个算法比较简单粗暴,比较容易想到,所以我们只需要敲一下代码即可: void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 但是这个算法简单,时间复杂度大,为O(n^2),讲一下另外一个算法: 定义三个变量,index指向第一个数组第m+n个位置,i指向第一个数组第m个位置,j指向第2个数组第n 个位置(我们需要从大到小比较赋值,如果从小到大比较,比较复杂,和第一个算法没有多大区别)。我们可以写出下列代码: void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 但是我们测试时用例不通过,这是因为如果nums1没有数据,无法进入循环,而且如果nums2还有数据的话,也没有拷贝过来,所以这个是不行的,故有 void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 这是三个题目,难度不是很大,但是我们需要理解里面的思想,并应用在之后的学习中,下节讲:单链表,不见不散,喜欢的可以一键三连哦。
{
int src = 1;
int dst = 0;
while (src < numsSize)
{
if (nums[src] != nums[dst] && ++dst != src)
{
nums[dst] = nums[src];
}
src++;
}
return dst + 1;
}
{
int i, j;
for (i = m; i < m + n; i++)
{
nums1[i] = nums2[i - m];
}
for (i = 0; i < m + n - 1; i++)
{
for (j = 0; j < m + n - 1 - i; j++)
{
if (nums1[j] > nums1[j + 1])
{
int tmp = nums1[j];
nums1[j] = nums1[j + 1];
nums1[j + 1] = tmp;
}
}
}
}
{
int index = m + n - 1;//这是下标
int i = m - 1;
int j = n - 1;
while (i > 0 && j > 0)
{
if (nums1[i] > nums2[j])
{
nums1[index--] = nums1[i];
}
else
{
nums1[index--] = nums2[j];
}
}
}
{
int index = m + n - 1;
int i = m - 1;
int j = n - 1;
while (i >= 0 && j >= 0)
{
if (nums1[i] > nums2[j])
{
nums1[index--] = nums1[i--];
}
else
{
nums1[index--] = nums2[j--];
}
}
//我们如果是nums1的数据没拷贝完全,本来就在第一个数组中,我们没必要拷贝,所以只用考虑第二个数组没有完全拷贝的情况
while(j >= 0)
{
nums1[index--] = nums2[j--];
}
}