双指针法:通过使用两个指针在一个for循环下完成两个for循环的工作
题目中要求原地移除所有数值等于val的元素,也就是说我们不能使用额外的数组来存储数据,应在原数组中进行改变元素
数组的元素在内存地址中是连续的,因此我们不能直接删除某个元素,只能进行覆盖
1.暴力解法:使用两层for循环,第一层for循环遍历数组每一个元素,第二层循环用于覆盖与val相等的元素。注意在覆盖后有当前i下标所指元素依然等于val的情况,要对i进行调整再次进行覆盖
int removeElement(int* nums, int numsSize, int val) {
for(int i=0;i<numsSize;i++)
{
if(nums[i]==val)
{
for(int j=i;j<numsSize-1;j++)
{
nums[j]=nums[j+1];
}
numsSize--;
}
if(nums[i]==val)
{
i--;
}
}
return numsSize;
}
2.双指针法:设置两个指针初始均指向数组首元素,fast指针遍历数组中每一个元素,last指针负责覆盖元素(可以理解为last指针在创建一个新的数组)fast所指元素不等于val时,slow指针向右移动,最终遍历后slow的大小即为题中所求k的大小
int removeElement(int* nums, int numsSize, int val) {
int fast=0,slow=0;
for(fast=0;fast<numsSize;fast++)
{
if(nums[fast]!=val)
{
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
例题2:977. 有序数组的平方 - 力扣(LeetCode)
1.暴力解法:题干很简单,最暴力的方法先将数组中每个数字都进行平方,再使用排序算法处理数组,最后返回数组,该方法容易想出但时间复杂度较高,我这里写的是冒泡排序,执行用时十分长,时间复杂度为O(n+n^2),可以使用快速排序这种效率更高的算法,但整体效率都不及接下来的双指针法
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
*returnSize=numsSize;
int* ret=(int*)malloc(sizeof(int)*numsSize);
for(int i=0;i<numsSize;i++)
{
ret[i]=nums[i]*nums[i];
}
for(int i=0;i<numsSize;i++)
{
for(int j=numsSize-1;j>i;j--)
{
if(ret[j]<ret[j-1])
{
int num=ret[j-1];
ret[j-1]=ret[j];
ret[j]=num;
}
}
}
return ret;
}
2.双指针法:我们发现,经过平方处理后的数组中,最大值一定出现在数组的最左端或者最右端,因此我们新建一个长度与原数组相同的空数组,设置两个指针分别指向数组左右两端,比较两端大小,将数值更大的一端的元素放入空数组的末端,从后往前填充空数组,再将左指针或右指针向内移动,直到左指针在右指针右边或二者相等,终止循环,返回排序后的数组。
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
*returnSize=numsSize;
int* ret=(int*)malloc(sizeof(int)*numsSize);
for(int i=0;i<numsSize;i++)
{
ret[i]=nums[i]*nums[i];
}
for(int i=0;i<numsSize;i++)
{
for(int j=numsSize-1;j>i;j--)
{
if(ret[j]<ret[j-1])
{
int num=ret[j-1];
ret[j-1]=ret[j];
ret[j]=num;
}
}
}
return ret;
}
双指针法在部分题中可以提高算法效率,降低时间复杂度,其思路不难理解,但代码实现需要注意细节部分的编写,避免出现数组越界等错误。