顺序表链表OJ题(1)——【LeetCode】

W...Y的主页 😊

代码仓库分享 💕


 前言:

今天我们来回顾一下顺序表与链表,针对这一块我们也有许多OJ题目供大家参考。当我们学习完顺序表链表后避免不了一些习题的练习,这样才能巩固我们学习的内容。

话不多说,我们开始进入OJ习题训练!!!

【leetcode 27.移除元素】 

OJ链接

给你一个数组 和一个值 ,你需要原地移除所有数值等于 的元素,并返回移除后数组的新长度。numsvalval

不要使用额外的数组空间,你必须仅使用 额外空间并原地修改输入数组O(1)

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

题目函数接口 nums:给定数组内容。numsSize:数组长度大小。val:移除元素。


题目要求原地删除数据,不能创建任何数组,这就会使原本简单的题变复杂。那我们应该怎么办呢?

首先我们最先想到的方法是遍历数组,遇到需要删除的内容就将数组后面的元素向前挪动一位,让其覆盖。但是这种方法非常”危险“,有可能导致数组越界,也有可能删除遗漏。所以这不是个好方法。

接下来将一个比较新颖且简单的方法:

双指针: 创建两个指针变量src与dst,两个指针全部指向数组开头。如果src指向的内容不是val,将src的内容赋值给dst,然后src与dst全部向后挪动一位。反之如果src指向的内容为val,dst保持原来的位置不动,src向后挪动一位。直至src指向数组的末尾结束。

 这个方法即保证没有创建任何数组空间复杂度为O(1),也优化了暴力遍历法中时间复杂度,从O(n^2)->O(n)。

代码展示:

nt removeElement(int* nums, int numsSize, int val){

    int ret = 0;
    int valp = 0;
    int n = numsSize;
    while(ret < numsSize)
    {
       
        if(nums[ret] != val)
        {
           nums[valp++] = nums[ret++];
        }
        else
            ret++;

    }
    return valp;
}

【leetcode 26.删除有序数组中的重复项】

OJ链接 

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

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被通过

题目函数接口: nums:升序数组。numsSize:数组中元素个数。


思路:快慢双指针

分析:创建两个指针变量fast与slow

如果两个指针指向内容全部相同,fast向后挪动一位slow不变。

如果两个指针指向不同内容,先让slow向后移动一位,再将fast指向的内容赋值给slow,再将fast向后移动一位即可。

等到fast指向数组末尾时,循环结束!

代码演示: 

int removeDuplicates(int* nums, int numsSize){
    int fast = 1;
    int slow = 0;
    int n = numsSize;
    while(fast < n)
    {
        if(nums[fast] != nums[slow])
        {
            slow++;
            nums[slow] = nums[fast];
        }
        else
        {

           fast++;
        }
        
    }
    return slow+1;

}

leetcode 88.合并两个有序数组】 

OJ链接

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

题目接口函数: 

nums1与nums2:两个非递减数组。nums1Size:nums1数组大小。nums2Size:nums2数组大小。m:nums1数组有效元素个数。n:nums2数组有效元素个数。


其实我们可以直接将两个数组进行归并,然后进行qsort排序直接完成。但是效率太低了,qsort函数底层原理为快速排序法,时间复杂度太高。

那有没有什么时间复杂度低的解法呢?

这道题本来可以两个数组进行比较,再开辟一个数组,两个数组元素进行比较,谁比较小就尾插到新数组中去。

但是这个题比较特殊,nums1开辟的空间比较大,可以放下两个数组的所有内容,所以我们必须将排序好的数组放入nums1中为了保证时间复杂度为O(m+n)。

但是我们可以使用这种方法的变形(三指针)。

解法:我们可以倒着比较,取大的依次从后往前插入。 创建三个指针,一个指向nums2数组末尾处,一个指向nums1有效元素末尾,还有一个指向nums1数组末尾处。

然后我们进行比较即可: 注意当end1与end2全部结束才可以结束循环,否则会有问题。

举例:num1:【5,6,7,0,0,0】,num2:【2,5,6】

 代码展示:



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

}

【leetcode 206.反转链表】

OJ链接

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

 题目接口函数:

head:链表头节点


我们在反转数组时,只需要两个指针一个指向头,一个指向尾进行交换即可,最后指向中间即可结束。但是单链表没有数组的特性,不能进行逆向读取,所以这个方法行不通。

现在提供两种方法:

方法一:创建3个指针n1、n2、n3分别指向NULL、head、head->next。标记好三个位置即可进行链表反转。 让n2->next指向n1,然后n1=n2、n2=n3、n3=n3->next即可

一直循环直到n3指向NULL时循环停止结束。

代码演示: 

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* a = NULL;
    struct ListNode* b = head;
    struct ListNode* c = NULL;
    if(b)
    c = b->next;
    if(head)
    {
        while(c)
        {
            a = b;
            b = c;
            c = b->next;
            b->next = a;
        
        }
        head->next = NULL;
        return b;
    }
    else
        return head;

 我们考虑问题就必须全面,如果链表中只有一个数则返回头指针head即可。

(头插法)方法二:

创建一个新链表头newhead,将旧链表元素挨个反向插入newhead中即可。

 

上述就是操作流程图!!!

代码演示:

struct ListNode* reverseList(struct ListNode* head){ 
struct ListNode* cur = head;
    struct ListNode*  newhead = NULL;
    while(cur)
    {
        struct ListNode* next = cur->next;
        cur->next = newhead;

        newhead = cur;
        cur = next;
    }
    return newhead;

}

【leetcode 203.移除链表元素】

OJ链接

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。 

 题目接口函数:

head:链表头节点。val:删除目标数


思路分析:移除目标元素,我们就要遍历链表进行查找。创建两个指针prev与cur,prev永远指向cur前一个节点,用来记录。

当cur遇到目标数时,我们就可以使用prev->next =cur->next,将目标数删除。直至cur指向NULL结束。

整体思路如下:

 虽然看上去很简单,但是这种题的“极端”情况非常多。我们必须把这些特殊情况考虑清楚再去写程序才能保证万无一失。

如果遇到上述情况,使用prev->next =cur->next就不实用了,程序就会出错。那我们应该怎么办呢?

我们应该在使用prev->next =cur->next时就先把元素为val的干掉,让head指向不是val的元素。 下面是代码演示:

struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode* prev = NULL, *cur = head;
    while(cur)
    {
        if(cur->val == val)
        {
            if(cur == head)
            {
                head = cur->next;
                free(cur);
                cur = head;
            }
            else
            {
                prev->next = cur->next;
                free(cur);
                cur = prev->next;
            }
        }
        else
        {
            prev = cur;
            cur = cur->next;
        }
    }
    return head;
}

还有一种思路更清晰的方法:

创建一个新的头节点newhead,让cur遍历链表,把元素内容不是val的挪下来与newhead链接即可。

这样的思路更清晰,空间复杂度对于之前方法一没有改变,但是时间复杂度增加了。因为在newhead尾插时要找尾节点。我们可以增加一个尾指针指向newhead链表的尾节点,这样就可以优化时间复杂度。

代码演示:

struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode* cur = head;
    struct ListNode* newhead = NULL, *tail = NULL;
    while(cur)
    {
        if(cur->val == val)
        {
            struct ListNode*der = cur;
            cur = cur->next;
            free(der);
        }
        else{
            if(tail == NULL)
            {
                newhead = tail = cur;
            }
            else{
                tail->next = cur;
                tail = tail->next;
            }
            cur = cur->next;
        }
        if(tail)
        {
            tail->next = NULL;
        }
    }
    return newhead;
}

 代码中有很多极端问题需要大家去想清楚,在这里就不过多讲述了,不懂可以私信我!!!

【leetcode 876.链表的中间节点】

OJ链接 

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

题目函数接口:

head:目标链表的头节点。


分析题目:这道题我们可以使用最原始的方法进行,先将链表遍历一遍求出链表长度,然后再次进行循环找出中间值即可。

但是有些公司面试会有题目限制要求,只让我们遍历一遍找出中间值。那我们应该怎么做呢?

(快慢指针):

我们创建两个指针变量slow与fast指向链表的头节点,slow一次只移动一个节点,而fast指针一次移动两个节点。当fast指向NULL时,我们的slow节点顺理成章的就找到了中间节点。

这种类型的题目我们就可以利用速度差来达到题目要求!

代码演示: 

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast&&fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

以上是本次全部内容,有错误或不同见解的希望与博主进行沟通交流,博主会继续努力将更好的博客内容带给大家,你们的三连是对博主最大的支持!!! ❤️❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/93682.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

illegal cyclic inheritance involving trait Iterable_2种解决方式

一、报错内容 /Users/liyangda/Code/DemoProject/demo-scala/src/scala/old04/T4.scala:11:20 illegal cyclic inheritance involving trait Iterableval value List(1, 2, 3, 4, 5, 6, 7, 8)二、问题解决 1、方式一&#xff1a;降低scala版本 可以选择降低Scala的版本&…

Python 字典排序超级简单

再Python中不可避免地要对字典进行排序&#xff0c;有时候字典里放着还是数组&#xff0c;对数组的某个位置元素进行排序&#xff0c;这样有点不容易 转换下思路&#xff0c;可以将字典放在Pandas中的DataFrame中&#xff0c;这样就可以迅速排序了。 import pandas as pd# 原…

深度学习7:生成对抗网络 – Generative Adversarial Networks | GAN

生成对抗网络 – GAN 是最近2年很热门的一种无监督算法&#xff0c;他能生成出非常逼真的照片&#xff0c;图像甚至视频。我们手机里的照片处理软件中就会使用到它。 目录 生成对抗网络 GAN 的基本原理 大白话版本 非大白话版本 第一阶段&#xff1a;固定「判别器D」&#x…

LeetCode面试经典150题(day 1)

LeetCode是一个免费刷题的一个网站&#xff0c;想要通过笔试的小伙伴可以每天坚持刷两道算法题。 接下来&#xff0c;每天我将更新LeetCode面试经典150题的其中两道算法题&#xff0c;一边巩固自己&#xff0c;一遍希望能帮助到有需要的小伙伴。 88.合并两个有序数组 给你两个…

iOS import包

Frameworks Frameworks 顾名思义就是框架&#xff0c;是第三方打包完成看不到源码&#xff0c;可以直接使用的 在项目中引用方式 OC 引用某一个文件&#xff0c;Frameworks一般会提供一个h文件引用全部其他文件 #import <JLRoutes/JLRoutes.h>swift 引用一个包&#x…

vue实现自定义树形组件

欢迎点击关注-前端面试进阶指南&#xff1a;前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的&#x1fa9c; 效果展示&#xff1a; 近期的一个功能需求&#xff0c;实现一个树形结构&#xff1a;可点击&#xff0c;可拖拽&#xff0c;右侧数据可以拖拽到对应的…

idea如何设置高亮显示选中的变量颜色

打开设置 设置颜色&#xff0c;挑你自己喜欢的&#xff0c;就好了 然后在你的编辑器页面里&#xff0c; 随便选中某个变量&#xff0c; 其他位置使用该变量的地方就会高亮显示

「Linux」使用VS Code远程连接Linux

一、VS Code简介 1.VS Code是什么&#xff1f; Visual Studio Code&#xff08;简称“VS Code”&#xff09;是微软公司的一个运行可以于 Mac OS、Windows 和 Linux之上的源代码编辑器。简单地说VS Code是一个编辑器&#xff0c;用来写代码。是一个基于插件的软件。 2.使用VSCo…

【多线程】Thread类的用法

文章目录 1. Thread类的创建1.1 自己创建类继承Thread类1.2 实现Runnable接口1.3 使用匿名内部类创建Thread子类对象1.4 使用匿名内部类创建Runnable子类对象1.5 使用lambda创建 2. Thread常见的构造方法2.1 Thread()2.2 Thread(Runnable target)2.3 Thread(String name)2.4 Th…

el-table 单击某一行,该行的前面的多选框显示已勾选

目 录 官网&#xff1a; 1. 单页面 2. table是组件 案例&#xff1a; 官网&#xff1a; 1. 单页面 通过单击获取当前行的数据&#xff0c;然后传给选中显示勾选的方法。 <template><el-tableref"multipleTable":data"tableData"tooltip-eff…

横扫“盲区”、“看透”缺陷,维视智造推出短波红外相机

在可见光领域&#xff0c;工业相机的视觉应用已经十分成熟&#xff0c;但在日常的客户咨询中&#xff0c;我们也经常接到一些“超纲需求”——客户想要检测“白底上的白色缺陷”、“不透明包装内的透明物体有无”等&#xff0c;均属于可见光无法实现的检测&#xff0c;而市面上…

C++ : implicit instantiation of undefined template ‘std::vector<_******>‘

编译报错 implicit instantiation of undefined template ‘std::vector<_struFontMap>’ 需要 #include add vector class

求解整数规划问题的割平面法和分支定界法

文章目录 整数规划割平面法分支定界法代码实现 整数规划 整数规划问题是优化变量必须取整数值的线性或非线性规划问题&#xff0c;不过&#xff0c;在大多数情况下&#xff0c;整数规划问题指的是整数线性规划问题。 其数学模型为 m i n f ( x ) c T x s.t A x b x ≥ 0 x…

Ansible学习笔记(二)

3.ansible的使用示例&#xff08;playbook&#xff09; 1.创建mysql 账户和mysql 组的 playbook ---#create mysql user and group - hosts: allremote_user: roottasks:- name: create groupgroup: namemysql systemyes gid306- name: create useruser: namemysql systemyes…

爬虫(bilibili热门课程记录)

什么是爬虫&#xff1f;程序蜘蛛&#xff0c;沿着互联网获取相关信息&#xff0c;收集目标信息。 一、python环境安装 1、先从Download Python | Python.org中下载最新版本的python解释器 2、再从Download PyCharm: Python IDE for Professional Developers by JetBrains中下…

【解决】idea启动spring MVC报错:一个或多个listeners启动失败Listener ClassNotFoundException

idea配置教程。tomcat调试报错Artifact :war exploded: Error during artifact deployment。 修改代码后&#xff0c;启动不生效&#xff0c;仍是旧代码。 根本原因是&#xff1a; Modules output path和Artifacts output directory不匹配 Modules output path一定要等于Ar…

Linux和其他类Unix系统的GNU coreutils 知多少

GNU coreutils是GNU项目的一部分&#xff0c;它是一组基本的命令行工具集&#xff0c;用于操作和管理Linux和其他类Unix系统中的文件和数据流。这些工具被广泛用于终端和脚本中&#xff0c;提供了许多常用的功能和实用程序。Linux和其他类Unix系统的GNU coreutils 知多少&#…

【JavaEE】Spring全家桶实现AOP-统一处理

【JavaEE】AOP&#xff08;2&#xff09; 文章目录 【JavaEE】AOP&#xff08;2&#xff09;1. 统一登录校验处理1.1 自定义拦截器1.2 将自定义拦截器加入到系统配置1.3 测试1.4 对于静态资源的处理1.5 小练习&#xff1a;统一登录拦截处理1.6 拦截器原理1.6.1 执行流程1.6.2 源…

习题练习 C语言(暑期第二弹)

编程能力小提升&#xff01; 前言一、表达式判断二、Assii码的理解应用三、循环跳出判断四、数字在升序数组中出现的次数五、整数转换六、循环语句的应用七、函数调用八、两个数组的交集九、C语言基础十、图片整理十一、数组的引用十二、数组的引用十三、字符个数统计十四、多数…

ssm校园快递一站式服务系统源码和论文

ssm校园快递一站式服务系统源码和论文076 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 选题的目的和意义&#xff1a; 目的&#xff1a; 校园快递一站式服务系统的研究目的有两个&#xff0c;一个为校园及…