【初阶数据结构与算法】顺序表与双指针算法详解
创作时间:
作者:
@小白创作中心
【初阶数据结构与算法】顺序表与双指针算法详解
引用
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)。
通过这三个例子,我们可以看到双指针算法在处理数组问题时具有较高的效率。在实际开发中,合理选择和使用算法可以显著提高程序的性能。
热门推荐
杉杉集团360亿负债压顶,行业不景气业绩大幅下滑
逆转客户满意度下降趋势,赋能物企品质提升、服务升级!(方案篇·下)
征地手续流程及时间怎么认定
宜昌悼亡歌舞:传承与创新的文化瑰宝
耗尽层和空间电荷区,耗尽层近似详解-KIA MOS管
DIY经济实惠NAS硬盘扩展方案:家庭用户的灵活存储选择
如何巧妙构思公司商标名称?
刘德与汉武帝刘彻:一段复杂的血缘与政治关系
红茶绿茶饮用禁忌:哪些健康状况下需避免饮用
持股一年以上分红免税的实际操作步骤详解,实现免税目标
南美洲有哪些国家?了解南美洲的主要国家和文化
消费者需求驱动小家电行业变革:企业如何应对?
如何了解乳胶漆的使用面积计算方法?这种计算方法在装修预算中有何重要性?
几十万负债压力大?教你如何化解家庭经济困境
深圳「超刺激」的徒步路线,很累很开心!
箫的指法基本练习教程【新版多篇】
文竹发芽长叶全过程剖析(从种子到翠绿的叶子)
工伤范围是什么?哪些情形构成工伤?
八字天干甲己合化在命理学中的解读
天眼新知 |小烧烤蕴藏“大科技”, 烧烤相关专利申请超万项
瘦肚子的饮食习惯和生活习惯
车载充电器怎么使用?USB车充使用误区有哪些?
小学教师资格证报考条件概览:学历背景及专业要求详解,报考资格全面解读
MySQL数据库表复制方法详解
特斯拉与超自然现象:科学视角下的“鬼魂”解析
五行缺金女孩如何取名(女孩缺金取什么名字好)
遂宁至云南自由行全攻略:必去景点、行程规划与旅行贴士
烧心打嗝食道灼热?这份饮食指南请收好
林宛瑜的幸福与烦恼:从《爱情公寓》看独立女性的成长与选择
2025退税指南:税优健康险和个税递延型养老保险详解