【数据结构】-- 顺序表OJ题


前言

上节我们讲到线性表之顺序表实现
这节我们来看看顺序表相关的OJ题


一、何为OJ题?

OJ(Online Judge)在线判定

常见的ACM、蓝桥杯、甚至NOIP等主流比赛中,无论实时出结果还是赛后统一评测,几乎都是以OJ作为评测系统的,即非人工主导,机器自主评测。这就是OJ - 全称为OnlineJudge,即在线评测系统。
由于程序设计类比赛,不仅仅要验证程序的正确与否,还要进行语法编译检测、内存、时间的检测等等,人工也很难做到,因此也只能使用OJ评测,以后找工作机试也是这样的形式。
常见的分类:

1.接口型

  • 不需要写头文件、主函数等等
  • 提交了以后,会跟oj服务器上他准备好的代码合并,再编译运行
  • 测试用例:通过参数过来的
  • 结果:一般是通过返回值拿的,也有可能是输出型参数
  • 只需要完善所给的函数
    在这里插入图片描述

2.IO型

  • 考试时IO型居多
  • 我们要自己写头文件、main函数等等
  • 测试用例输入:需要使用scanf来获取
  • 测试结果:需要printf输出
    在这里插入图片描述

二、顺序表(数组)OJ题

1.移除元素

LeetCode链接:https://leetcode.cn/problems/remove-element/
在这里插入图片描述

题目:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
函数:

  • 返回值:int – 移除后数组的新长度
  • 函数参数:nums – 指向数组首元素的指针 ; numsSize – 数组大小 ; val – 需移除元素的值

思路一:

找到所有的val,依此挪动数据覆盖删除。

时间复杂度:O(N^2) – 最坏的情况:数组中全部都是val

思路二:

以空间换时间
一次遍历nums数组,把不是val的值,放到tmp数组,再把tmp数组的值拷贝回去。

时间复杂度:O(N) – 最坏的情况:数组中全部都是val
空间复杂度:O(N)

能否时间复杂度优化到O(N)? 空间复杂度优化为O(1)?

思路三:

利用两个下标 - src(source)  dst(destination) , 与双指针类似,直接原地覆盖删除。

时间复杂度:O(N)
空间复杂度:O(1)

具体步骤:

  1. 定义两个下标,从数组的第一个元素开始
  2. src去找nums数组中不等于val的值,放到dst指向的位置去,再src++,dst++
  3. src下标的值若等于val,就src++继续往后走,src < numsSize

过程图:

以此类推,直到src == numsSize 就不继续了
此时下标dst恰好就是移除后数组的新长度

代码:

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

2.删除有序数组中的重复项

LeetCode链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
在这里插入图片描述

题目:
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

函数:

  • 返回值:int – 移除后数组的新长度
  • 函数参数:nums – 指向数组首元素的指针 ; numsSize – 数组大小

思路:
这题思路与上题类似,需要原地删除重复出现的元素,则时间复杂度:O(N) 空间复杂度:O(1)
利用三个下标,i,j,dst ,i 和 j 用来比较,dst用来记录存放数据的位置,实现原地去重

具体步骤:

  1. i = 0 ; j = 1 ; dst = 0 ;
  2. 当nums[i] == nums[j]时,j++,j继续往前走
  3. 当nums[i] != nums[j]时,nums[dst] = nums[i],dst++,i = j,j++

过程图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
代码:

int removeDuplicates(int* nums, int numsSize){
    int i = 0, j = 1;
    int dst = 0;
    while(j < numsSize)
    {
        if(nums[i] == nums[j])
        {
            j++;
        }
        else
        {
            nums[dst] == nums[i];
            dst++;
            i = j;
            j++;
        }
    }
    nums[dst] == nums[i];
    dst++;

    return dst;
}

结语

如果本文对你有帮助,希望 三连 支持一下!若有错误,感谢指正!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值