【初阶数据结构与算法】顺序表与双指针算法详解
创作时间:
作者:
@小白创作中心
【初阶数据结构与算法】顺序表与双指针算法详解
引用
CSDN
1.
https://m.blog.csdn.net/hdxbufcbjuhg/article/details/143505937
本文将通过三个具体的LeetCode题目,讲解顺序表和双指针算法在处理数组问题中的应用。通过这些实例,读者可以更好地理解这两种方法的实现和优化过程。
顺序表练习
在顺序表练习中,我们会首先使用顺序表来解决,然后再介绍其它方法。在练习开始之前,需要说明的是,在实际开发中,我们通常不需要手写数据结构,因为现代编程语言(如C++的STL)中都有现成的数据结构可以使用。但在学习阶段,手写数据结构有助于加深理解。
在做题过程中,我们也会计算这些方法的时间复杂度和空间复杂度,也是对之前内容的一个复习。
1.移除数组中指定的元素
方法1(顺序表)
方法1的思路是直接使用顺序表。在顺序表中,我们提供了查找方法,并且提供了删除指定位置元素的方法。具体步骤如下:
- 创建顺序表并初始化
- 将数组中的内容尾插到顺序表
- 使用循环查找要删除的元素,并将其删除
- 将顺序表中的内容重新放入原数组
代码实现如下:
int removeElement(int* nums, int numsSize, int val)
{
int i = 0;
SL sl;
SLInit(&sl);
for(i = 0; i<numsSize; i++)
{
SLPushBack(&sl,nums[i]);
}
while(SLFind(&sl,val) != -1)
{
int ret = SLFind(&sl,val);
SLErase(&sl,ret);
}
for(i = 0; i<sl.size; i++)
{
nums[i] = sl.arr[i];
}
int k = sl.size;
SLDestroy(&sl);
return k;
}
这种方法的时间复杂度为O(N^2),空间复杂度为O(N)。
方法2(双指针)
双指针算法的核心思想是使用两个指针(或下标)来处理数组。具体步骤如下:
- 初始化两个指针
src
和dest
,都指向数组的第一个元素 - 遍历数组,如果
src
位置的值等于要删除的值,就直接让src
往后走一步 - 如果不等于,就把
src
位置的值赋给dest
,随后让dest
和src
都往后走一步
代码实现如下:
int removeElement(int* nums, int numsSize, int val)
{
int src = 0;
int dest = 0;
while(src < numsSize)
{
if(nums[src] == val)
{
src++;
}
else
{
nums[dest++] = nums[src++];
}
}
return dest;
}
这种方法的时间复杂度为O(N),空间复杂度为O(1)。
2.删除有序数组中的重复项
方法1(顺序表)
方法1的思路与上一题类似,使用顺序表来处理数组。具体步骤如下:
- 创建顺序表并初始化
- 将数组中的内容尾插到顺序表
- 使用循环查找重复元素并删除
- 将顺序表中的内容重新放入原数组
代码实现如下:
int removeDuplicates(int* nums, int numsSize)
{
SL sl;
int i = 0;
SLInit(&sl);
for (i = 0; i < numsSize; i++)
{
SLPushBack(&sl, nums[i]);
}
for (i = 0; i < numsSize; i++)
{
if (i + 1 < numsSize && sl.arr[i] == sl.arr[i + 1])
{
SLErase(&sl, i);
numsSize--;
i--;
}
}
for (i = 0; i < numsSize; i++)
{
nums[i] = sl.arr[i];
}
SLDestroy(&sl);
return numsSize;
}
这种方法的时间复杂度为O(N^2),空间复杂度为O(N)。
方法2(双指针)
双指针算法的核心思想是使用两个指针(或下标)来处理数组。具体步骤如下:
- 初始化两个指针
src
和dest
,src
指向第二个元素,dest
指向第一个元素 - 遍历数组,如果
src
位置的值等于dest
位置的值,就直接让src
往后走一步 - 如果不等于,就让
dest
先++,再把src
位置的元素赋值给dest
位置的元素,最后让src
++
代码实现如下:
int removeDuplicates(int* nums, int numsSize)
{
int src = 0, dest = 0;
while(src < numsSize)
{
if(nums[src] == nums[dest])
src++;
else
nums[++dest] = nums[src++];
}
return dest+1;
}
这种方法的时间复杂度为O(N),空间复杂度为O(1)。
3.双指针练习之合并两个有序数组
方法1(直接排序)
最简单的方法是将两个数组合并后直接排序。代码实现如下:
#include <stdlib.h>
int int_cmp(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)
{
for(int i = 0; i<n; i++)
{
nums1[i+m] = nums2[i];
}
qsort(nums1, m+n, sizeof(int), int_cmp);
}
这种方法的时间复杂度为O(N * logN),空间复杂度为O(1)。
方法2(双指针)
双指针算法的核心思想是使用两个指针(或下标)来处理两个数组。具体步骤如下:
- 初始化两个指针
src1
和src2
,分别指向两个数组的有效元素的最后一个位置 - 初始化
dest
指针,指向合并后数组的最后一个位置 - 比较
src1
和src2
指向的元素,将较大的元素放入dest
位置,然后让dest
、src1
或src2
减1 - 如果
src2
还有剩余元素,将其全部移动到nums1
中
代码实现如下:
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
int src1 = m-1;
int src2 = n-1;
int dest = m+n-1;
while(src1>=0 && src2>=0)
{
if(nums1[src1] > nums2[src2])
{
nums1[dest--] = nums1[src1--];
}
else
{
nums1[dest--] = nums2[src2--];
}
}
while(src2 >=0)
{
nums1[dest--] = nums2[src2--];
}
}
这种方法的时间复杂度为O(N),空间复杂度为O(1)。
通过这三个例子,我们可以看到双指针算法在处理数组问题时具有较高的效率。在实际开发中,合理选择和使用算法可以显著提高程序的性能。
热门推荐
虾仁的挑选指南:从外观到烹饪表现全方位解析
计算机辅助设计(CAD)在工程领域的应用与优势
成交量变化中的投资密码:如何识别蓝筹白马股的买卖时机?
社保工伤赔偿项目及申请流程全攻略
常见的十大鸡心做法 鸡心怎么做才好吃
转化型抢劫与标准抢劫的区别在于
河马在遭到狮子攻击时咬伤路虎
南人北相与北人南相:古代相学中的地域文化密码
XML数据如何导入到数据库
厦门天竺山最全旅游攻略
BT磁力种子链接使用指南:工作原理、优势及安全注意事项
辩证思维,让我们更客观、全面、深入地认识事物
经常放屁且声音很大?可能是这些原因
香港律师事务所查询攻略:从分类到服务范围的全方位指南
定点整治+溯源追究!即日起广州严查严管“电鸡”违法行为
宿营车市场火热,但国家认可吗?参考标准有哪些?
公司IPO上市准备时间及准备工作
无碘盐和加碘盐有什么区别?
八字排盘五行属性
紫山药该怎么种植?紫山药栽培技术简介
108颗白玉手串:品质挑选指南与搭配建议全解析
在北京什么时候种花最好?50多种花卉推荐
孩子和成人都适用的提高专注力的方法
理财产品的收益率到底怎么看?
川企大调研·“宝藏”企业成长记⑭丨长虹新网科技的“不变”与“变”
艺考美术就业前景怎么样,艺考美术发展方向
Photoshop制作乌鸦羽毛黑白单色插图教程
特殊儿童的诊断评估-第2章-特殊儿童的特征及诊断与鉴别标准2
知战善教,一名优秀的军校教员是怎么炼成的?
8分眼渔网的大小及对应捕捞对象