顺序表相关练习题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


一、原地移除数组中所有的元素val,要求时间复杂度为O(n),空间复杂度为O(1)

1.1 思路一:挪动数据

思路一:从头开始遍历,找到目标元素val,就挪动数据进行覆盖

c 复制代码
//思路1:挪动数据
#include<assert.h>
void Erase(int* nums, int pos, int len)
{
	//因为题目给的是数组,所以我们要对顺序表的任意删做点改变
	//比如给出第三个参数长度
	assert(len > 0);    //如果长度小于等于0,就报错
	while (pos < len - 1)
	{
		nums[pos] = nums[pos + 1];  //用数组的方式覆盖
		pos++;  //下标++,向后移动
	}
}

int removeElement(int* nums, int numsSize, int val)
{
	assert(nums);   //nums不能为空指针
	for (int i = 0; i < numsSize; i++)
	{
		if (nums[i] == val)
		{
			Erase(nums, i, numsSize--);
			i--;//这里要--的原因是防止漏掉val,多判断一次
		}

	}
	return numsSize;
}

1.2 思路二:创建新的数组,以空间换时间

创建一个额外的数组,对原数组进行遍历判断,如果元素不等于val,就可以放入新数组中

c 复制代码
//思路2,以空间换时间
#include<stdlib.h>
#include<assert.h>
int removeElement(int* nums, int numsSize, int val)
{
    int* pa = (int*)malloc(sizeof(int) * numsSize); //动态申请内存
    assert(pa); //预防申请失败的情况
    int i = 0;  //原数组的下标
    int j = 0;  //新数组的下标
    for (i = 0; i < numsSize; i++)
    {
        //如果不是目标值,就将其放入到新数组中
        if (nums[i] != val)
            pa[j++] = nums[i];  //vs中会报一个小警告,原因pa[j]可能会越界,可不管
    }
    //将新数组中的元素注入到原数组中
    for (i = 0; i < j; i++)
        nums[i] = pa[i];

    free(pa);   //释放空间
    pa = NULL;  //指针置空
    return j;   //此时新数组的下标就是有效元素数
}

1.3 思路三:双指针覆盖

用到了双指针,对数组内元素进行覆盖,具体实现为:

c 复制代码
int removeElement(int* nums, int numsSize, int val)
{
	int src=0, dst = 0;
	while (src < numsSize)
	{
		if (nums[src] == val)
		{
			src++;
		}
		else
		{
			nums[dst] = nums[src];
			dst++;
			src++;
		}
	}

	return dst; //返回的是删除后的数组长度
}

二、删除排序数组中的重复项

思路:

定义变量:dst=1;cur=0;next=1;

cur和next相等,则next++

cur和next不相等,则nums[dst]=nums[next];dst++;cur=next;next++;

c 复制代码
int removeDuplicates(int* nums, int numsSize) {
   if (numsSize == 0) 
    return 0;
   int dst=1;
   int cur=0,next=1;
   while(next<numsSize)
   {
       
       if(nums[cur]==nums[next])
       {
        next++;
        
       }
       else
       {
        nums[dst]=nums[next];
        dst++;
        cur=next;
        next++;
       }
   }
    return dst;
}

三、合并两个有序数组

思路:将两个数组从后往前进行比较,小的尾插到新数组,若相等,随便插哪个都可以

c 复制代码
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int end1=m-1;
    int end2=n-1;
    int dst=m+n-1;
    while(end1>=0&&end2>=0)
    {
        if(nums1[end1]>nums2[end2])
        {
            nums1[dst--]=nums1[end1--];
        }
        else
        {
            nums1[dst--]=nums2[end2--];
        }
    }
    while(end2>=0)
    {
        nums1[dst--]=nums2[end2--];
    }
    
}

四、数组形式的整数加法

思路:模拟竖式加法,就像我们在纸上做加法一样,从右往左逐位相加,处理进位

  1. 确定最大长度:结果的最大可能长度是输入数组长度和k的位数中的较大值再加1(因为可能有进位)
  2. 逆向处理:从数字的最低位(数组末尾)开始处理,逐步向高位移动
  3. 三位一体处理:同时考虑数组的当前位、k的当前位和上一位的进位值
  4. 动态计算:在循环中同时处理数组位数和k的位数,确保两者都能完全处理
  5. 智能返回:通过指针算术直接返回有效结果部分,避免不必要的数组复制或反转
c 复制代码
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* addToArrayForm(int* num, int numSize, int k, int* returnSize) {
    
	// 计算可能的最大长度
	int maxLen = numSize > 10 ? numSize + 1 : 11; // k最多10位(2^31-1是10位数)
	int* result = (int*)malloc(sizeof(int)* maxLen);

	int carry = 0;//用于存储进位值
	int index = maxLen - 1; // 从数组末尾开始填充

	// 从最低位开始相加
	for (int i = numSize - 1; i >= 0 || k > 0 || carry > 0; i--) {
		int digit = carry;
		if (i >= 0) digit += num[i];
		if (k > 0) {
			digit += k % 10;
			k /= 10;
		}

		carry = digit / 10;
		result[index--] = digit % 10;
	}

	// 计算实际结果长度
	*returnSize = maxLen - 1 - index;

	// 返回指向第一个有效数字的指针
	return result + index + 1;
}

注:// 返回指向第一个有效数字的指针

return result + index + 1;

这里使用了一个基本概念指针算术

在c语言中,当我们对指针进行加减运算时,实际上是按指针指向的数据类型的大小来移动指针

例如:

c 复制代码
int* ptr;//指向一个整数
ptr+1;//会移动到下一个整数(地址增加sizeof(int)字节)
相关推荐
ᐇ95921 小时前
Java HashMap深度解析:数据结构、原理与实战指南
java·开发语言·数据结构
十八岁讨厌编程21 小时前
【算法训练营 · 补充】LeetCode Hot100(中)
算法·leetcode
橘颂TA21 小时前
【剑斩OFFER】算法的暴力美学——最小覆盖字串
算法·c/c++·就业
wearegogog12321 小时前
基于混合蛙跳算法和漏桶算法的无线传感器网络拥塞控制与分簇新方法
网络·算法
Tiandaren1 天前
大模型应用03 || 函数调用 Function Calling || 概念、思想、流程
人工智能·算法·microsoft·数据分析
2301_795167201 天前
玩转Rust高级应用 如何进行理解Refutability(可反驳性): 模式是否会匹配失效
开发语言·算法·rust
云知谷1 天前
【C/C++基本功】C/C++江湖风云录:void* 的江湖传说
c语言·开发语言·c++·软件工程·团队开发
小当家.1051 天前
[LeetCode]Hot100系列.贪心总结+思想总结
算法·leetcode·职场和发展
墨雪不会编程1 天前
数据结构—排序算法篇二
数据结构·算法·排序算法
wydaicls1 天前
C语言完成Socket通信
c语言·网络·websocket