顺序表相关练习题

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

文章目录


一、原地移除数组中所有的元素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)字节)
相关推荐
宋一平工作室8 小时前
嵌入式人别再瞎折腾了!这8个开源项目,解决按键/队列/物联网所有痛点,小白也能抄作业
c语言·stm32·单片机·嵌入式硬件·物联网·开源
緈福的街口8 小时前
【leetcode】130. 被围绕的区域
算法·leetcode·职场和发展
THMAIL8 小时前
机器学习从入门到精通 - KNN与SVM实战指南:高维空间中的分类奥秘
人工智能·python·算法·机器学习·支持向量机·分类·逻辑回归
皆过客,揽星河8 小时前
c语言程序之魂——算法(练习题,流程图,程序源码)
c语言·算法·流程图·源码·辗转相除法·c语言程序设计
zc.ovo9 小时前
牛子图论1(二分图+连通性)
数据结构·c++·算法·深度优先·图论
ShineWinsu9 小时前
对于牛客网—语言学习篇—编程初学者入门训练—复合类型:BC141 井字棋及BC142 扫雷题目的解析
c语言·练习·小游戏·扫雷·牛客网·五子棋·井字棋
丑小鸭是白天鹅9 小时前
嵌入式C语言之链表冒泡排序
c语言·开发语言·链表
通往曙光的路上9 小时前
JAVA 十二幕啦啦啦啦啦啦啦啊啦啦啦啦a
java·开发语言·算法
得物技术9 小时前
得物灵犀搜索推荐词分发平台演进3.0
算法·架构·排序算法