C C++最新顺序表C语言实现附加力扣题,C C++技术图谱

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取


### 顺序表扩容



> 
> 面对空间已满,没法再插入数据的情况,需要增容
> 
> 
> 



//扩容
void SeqListCreate(SeqList *ps)
{
assert(ps);
//空间满了开辟一块新的空间
if (ps->capacity == ps->size)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
int *newA = (int *)realloc(ps->arr, sizeof(int) * newcapacity);
if (newA == NULL)
{
perror(“SeqListCreate:”);
exit(1);
}

	ps->arr = newA;
	ps->capacity = newcapacity;
}

}


### 顺序表的头插



> 
> 头插数据需要考虑是从前往后挪动数据还是从后往前挪动数据,很明显如果是从前往后挪动数据的话,会将原有的数据给覆盖掉,所以只能从后往前,头插的时间复杂度是o(n)
> 
> 
> 



//头插
void SeqListPushFront(SeqList *ps,int x)
{
assert(ps);
SeqListCreate(ps);
int end = ps->size - 1;
//从后往前挪动数据
while (end >= 0)
{
ps->arr[end + 1] = ps->arr[end];
end–;
}
//头插数据
ps->arr[0] = x;
ps->size++;
}


### 顺序表的尾插



> 
> 其实顺序表的尾插,时间复杂度o(1)
> 
> 
> 



//尾插
void SeqListPushBack(SeqList *ps,int x)
{
assert(ps);
SeqListCreate(ps);
ps->arr[ps->size++] = x;
}


### 顺序表的遍历打印



> 
> 遍历顺序表,o(n)的时间复杂度
> 
> 
> 



//打印
void SeqListprint(SeqList * ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ",ps->arr[i]);
}
}


### 顺序表的尾删



> 
> 这里要考虑的是需要判断表中有没有数据,如果没有数据就不需要删除
> 
> 
> 



//尾删
void SeqListPopBack(SeqList *ps)
{
assert(ps);
assert(ps->size > 0);
ps->size–;
}


### 顺序表的头删



> 
> 将后一个数据覆盖掉前一个数据,最后- -size,因为需要挪动数据所以时间复杂度是o(n)
> 
> 
> 



//头删
void SeqListPopFront(SeqList *ps)
{
assert(ps);
assert(ps->size > 0);
int begin = 0;
while (begin < ps->size)
{
ps->arr[begin] = ps->arr[begin + 1];
begin++;
}
ps->size–;
}


### 顺序表的查找



> 
> 找到返回该位置的下标,O(N)时间复杂度
> 
> 
> 



//查找
int SeqListFind(SeqList * ps, int x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
return i;
}
}
return -1;
}


### 删除



> 
> 删除指定pos位置的元素,可以挪动数据将其覆盖,从前往后的覆盖法,挪动数据时间复杂度O(N)
> 
> 
> 



//删除
void SeqListErase(SeqList *ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
int begin = pos;
while (begin < ps->size)
{
ps->arr[begin] = ps->arr[begin + 1];
++begin;
}
ps->size–;
}


### 插入



> 
> 将pos位置和pos后的数据整体往后一挪动,再将x插入到指定pos位置,注意选择的位置不能超出顺序表的大小  
>  时间复杂度O(N)
> 
> 
> 



void SeqListInsert(SeqList *ps, int pos, int x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
SeqListCreate(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->arr[end + 1] = ps->arr[end];
end–;
}

ps->arr[pos] = x;
ps->size++;

}


### 修改



> 
> 修改该位置的值
> 
> 
> 



void SeqListmodif(SeqList *ps, int pos, int x)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
ps->arr[pos] = x;
}


## 顺序表的问题及思考:


1、顺序表的指定插入和删除都需要挪动数据,时间复杂度为O(N)  
 2、增容需要申请空间,拷贝数据,释放就空间,会有不小的消耗,一定程度上也会影响效率,增容会存在空间浪费,开大了浪费,开小了又不够


## 力扣题


### 27. 移除元素:


[点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/67574c9ed20f4ef3bd5ba9ca47ed93a4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **思路一:**  
 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入,找出值为val的位置挪动后面的数据覆盖掉val的值,  
 时间复杂度是0(N\*N),考虑最坏的情况如果数组中的值全是val的话,每次找出一个值为val的时间复杂度是o(N),挪动数据又是o(N),整体就是O(N \* N)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b4f3ade34d694410b464a01f374a2645.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_16,color_FFFFFF,t_70,g_se,x_16)  
 **思路二:**  
 开辟一个空间足够大的数组,遍历一遍找出原数组将值不为val的,拷贝到新数组中去,时间复杂度是O(N),空间复杂度是O(N)。空间换时间


**思路三:**  
 双指针解法,在原数组的基础上创建一个虚拟数组,src和dest都从0开始,src去找值不为val的,找到后将src位置的值覆盖掉dest位置的值,他们都自增,如果src的值等于val,src就继续找,最后返回dest,时间复杂度是O(N),空间复杂度是O(1),  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0741d398ed4349a3bd3902d9dbe1a856.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



int removeElement(int* nums, int numsSize, int val){
if(numsSize == 0)
return 0;
int dest = 0;
int src = 0;
while(src < numsSize)
{
if(nums[src] != val)
{
nums[dest++] = nums[src++];
}
else
{
src++;
}
}

return dest;

}


### 26. 删除有序数组中的重复项:


[点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b08901e308ab4f2987fe2e0aa26dc07b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **解题思路:**  
 src和next一前一后,如果src的值不等于dst,就将src的值覆盖在dst的位置上,dst++,next的位置赋值给src,next++找下一个数,在回来判断next位置的值是否与src相等,如果相等继续执行,直到条件为假循环终止  
 时间复杂度是O(N),空间复杂度是O(1)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20e0b53abb204f1cace9db9d44364fd0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 考虑这种情况,如果next已经 > numsize了,循环终止,但是末尾的那个元素还没有拷贝过来  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/47c09bd674e042f1b2e8bc78eafa2b6f.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



int removeDuplicates(int* nums, int numsSize){
if(numsSize == 0)
{
return 0;
}
int cur = 0;
int next = 1;
int count = 0;
int dest = 0;
while(next < numsSize)
{
//cur和next将重复的值给过滤掉,只留下一个值给dst
if(nums[cur] != nums[next])
{
nums[dest++] = nums[cur];
cur = next;
++next;
}
else
{
++next;
}
}
//防止循环终止后,最后一个数据丢失
if(cur < numsSize)
nums[dest++] = nums[cur];
return dest;
}


### 27. 数组形式的整数加法:


28. [点我](https://bbs.csdn.net/topics/618668825).  
 . ![在这里插入图片描述](https://img-blog.csdnimg.cn/653f9da8da794b9994026e3591f3b8f1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **测试用例**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2109da90ea364a26aa63e92090d34366.png)



> 
> 解题思路:  
>  计算出val的十进制位数,取val或数组长度大的那一个作为新数组的大小(存在进位问题),继续将val的每一位取下来对应的个位、十位、百位…看成与数组元素的一种关联关系,通过不断拆分相加它们之间的和,和值大于10就考虑进位,小于10不进位,最后将这两个值相加得到的和存放到对应的位置上,由于是从低位开始计算的,存在数组的顺序也是倒过来的,所以再最后需要整体一逆转
> 
> 
> 



int* addToArrayForm(int* A, int numSize, int k, int* returnSize){
int ksize = 0;
int num = k;
//记录num的十进制位数
while(num)
{
num /= 10;
++ksize;
}

int reti = 0;
//扩容一位提供进位
int len = numSize > ksize ? numSize + 1 : ksize + 1;
int Ai = numSize - 1;
int ki = 0;
int next = 0;//进位
int \*retArr = (int \*)malloc(sizeof(int) \* len);
while(Ai >= 0 || ki < ksize)
{

    int aval = 0;
    if(Ai >= 0)
    aval = A[Ai--];

    int kval = k % 10;
    k /= 10;
   
    ki++;
    int ret = kval + aval + next;
    if(ret >= 10)
    {   
        next = 1;
        ret -= 10;
    }
    else
    {
        next = 0;
    }
    retArr[reti++] = ret;
}
//存放最高位
if(next == 1)
{
    retArr[reti++] = 1;
}
//逆置数组
int begin = 0;
int end = reti - 1;
while(begin < end)
{
    int tmp = retArr[begin];
    retArr[begin] = retArr[end];
    retArr[end] = tmp;

    begin++;
    end--;
}
\*returnSize = reti;
return retArr;

}


### 旋转数组:


[点我](https://bbs.csdn.net/topics/618668825).  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/055e9233a72448c5b15ee8e07f53825c.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)



> 
> 解题思路:  
>  将数组整体旋转一次,以k为划分左旋转0 ~ k - 1这个区间,  
>  右旋转k ~ numsize - 1区间,整体就是旋转k次的数组,有点类似于左旋转字符串,时间复杂度是O(N + N),还是O(N)  
>  ![在这里插入图片描述](https://img-blog.csdnimg.cn/9bab310a91f4453da1bfa368f37df72e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASVTojqvmiY7nibk=,size_20,color_FFFFFF,t_70,g_se,x_16)
> 
> 
> 



//逆置数组
void reverse(int* nums1,int *nums2)
{
while(nums1 < nums2)
{
int tmp = *nums1;
*nums1 = *nums2;
*nums2 = tmp;

   ++nums1;
   --nums2;

}

}

void rotate(int* nums, int numsSize, int k){
if(k >= numsSize)
k %= numsSize;
//整体旋转
reverse(nums, nums + numsSize - 1);
//左旋转
reverse(nums,nums + k - 1);
//右旋转
reverse(nums + k,nums + numsSize - 1);

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

t* nums, int numsSize, int k){
if(k >= numsSize)
k %= numsSize;
//整体旋转
reverse(nums, nums + numsSize - 1);
//左旋转
reverse(nums,nums + k - 1);
//右旋转
reverse(nums + k,nums + numsSize - 1);

[外链图片转存中…(img-zR5uxVRv-1715733485682)]
[外链图片转存中…(img-9jIwBSfw-1715733485682)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值