当前位置: 首页 > news >正文

链表OJ经典题目及思路总结(一)

目录

  • 前言
  • 1.移除元素
    • 1.1 链表
    • 1.2 数组
  • 2.双指针
    • 2.1 找链表的中间结点
    • 2.2 找倒数第k个结点
  • 总结

前言

解代码题
先整体:首先数据结构链表的题一定要多画图,捋清问题的解决思路;
后局部:接着考虑每一步具体如何实现,框架搭好后,处理坑点,考虑细枝末节,通常要考虑以下几个容易出错的点

  1. 需要单独处理的头结点、尾结点
  2. 越界问题
  3. 头指针为NULL
  4. 循环继续、结束条件等

而思路这一块,有的思路好想,但是无论从时间复杂度还是空间复杂度上来看,可能不是优良的算法。但有一些比较清奇的思路,见得题多了,反思总结,也就收入囊中啦!比如下面介绍的双指针,以及翻转数组的思路都很优秀。

每个小节开头蓝色字体是题目链接,大家可以先做一下题~


1.移除元素

1.1 链表

203.移除链表元素(题目链接)
在这里插入图片描述
思路1:遍历链表,删除数据域为val的结点;
思路2:将值不为val的节点尾插到新的链表中,返回新链表的头结点(头指针)。

注意:两种思路整体都是遍历原链表,但是有几个坑!

  • 坑点1:如果尾插第一个结点,要更改新的头指针newhead;但后续插入不需要再更改头指针。
  • 坑点2:如果最后一个结点的值不是val,那么将其尾插到新链表,其next指针域为NULL;但是如果最后一个结点的值是val,其前一个结点(假设prev指向该结点)被尾插到新链表,prev->next指向的最后一个节点(数据域为val)被free,那么prev->next是野指针,所以要将其置为NULL.

比如下图中当数据域为5的结点被尾插到新链表之后,tail指向该节点,tail->next=p,但是free§之后,p就是野指针了,应将tail->next手动置为NULL.
在这里插入图片描述

  • 坑点3:第二点和链表本身为空可以合在一起考虑,如果head为NULL,那么cur为NULL,遍历原链表的while循环不会执行,tail为NULL,newhead为NULL,直接返回即可;而如果tail不为NULL,tail->next有可能为NULL,不考虑太多,直接置为NULL.
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/ 
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* cur=head, *newhead=NULL, *tail=NULL;//cur用于遍历要删除的链表//newhead用于存放要新链表的头指针,用于返回//tail用于尾插,否则每次尾插都要遍历新链表找尾节点,效率不高while(cur)//while循环遍历要删除的链表{//结点数据域为val与非val分开处理,val则删除,非val则尾插到新链表if(cur->val!=val){//插入第一个元素和后续元素不同的是,插入第一个元素需要更改头指针,要单独处理//坑点1 if(tail==NULL)newhead=tail=cur;else{tail->next=cur;tail=tail->next;}cur=cur->next;}else{struct ListNode* next=cur->next;free(cur);cur=next;}}//坑点2,3if(tail)tail->next=NULL;return newhead;
}

1.2 数组

27.移除元素(题目链接)
在这里插入图片描述
这个题的思路可以是,创建一个新的数组存储值不为val的数组元素。
也可以使用双指针,数组的指针就是下标,使用src指针遍历数组,如果值不为val,就将其赋值到nums[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++];//只有当值非val的时候,存储到数组中,以dst为指针,也就是舍弃值为val的元素elsesrc++;//每次循环src都++,达到遍历数组的目的}return dst;
}

2.双指针

2.1 找链表的中间结点

876.链表的中间结点(题目链接)
在这里插入图片描述
考虑快慢指针,fast, slow指针刚开始均指向第一个结点,接着fast每次走两步,slow每次走一步;如果是奇数结点,fast->next为NULL时,slow指向中间结点;如果是偶数结点,fast为NULL时,slow指向两个中间结点的第二个结点。也即fast遍历链表,当fast为NULL或fast->next为NULL时停止循环,返回slow.
在这里插入图片描述

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode* middleNode(struct ListNode* head) {struct ListNode* fast=head,*slow=head;while(fast && fast->next){fast=fast->next->next;slow=slow->next;}return slow;
}

这个思路和下面这道题有点像!

2.2 找倒数第k个结点

02.返回倒数第k个节点(题目链接)
在这里插入图片描述
思路:考虑双指针,fast走到NULL终止循环,那么此时fast相当于倒数第0个结点,slow是倒数第k个结点,也即fast比slow多走了k步,那么让fast先走k步,接着fast和slow同步往前走,直到fast为NULL.
代码如下
(如果fast走到最后一个节点停止,那么考虑fast先走k-1步)

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
int kthToLast(struct ListNode* head, int k){struct ListNode* fast=head,*slow=head;while(k--){if(fast==NULL)return NULL;//考虑链表本身为空的情况fast=fast->next;}while(fast){fast=fast->next;slow=slow->next;}return slow->val;
}

总结

链表代码题考虑时间复杂度、空间复杂度,同时要多见题,多见经典题,多练,总结经典思路,以及常见坑点,写代码时考虑细枝末节。细节考虑不到位,可能存在提交不通过,对未通过测试用例的提示进行分析,调试,提升自身解决问题的能力。

相关文章:

  • 【计算机网络超强概念总结】第二章 物理层
  • 欧几里得8月模考总结
  • 使用容器启动的zk无法暴露3888问题解决
  • 创建数据/采集数据+从PI数据到PC+实时UI+To PLC
  • Solaris11.4配置远程桌面登录
  • 基于SpringBoot+Vue的毕业设计选题管理系统
  • 一篇文章快速学会docker容器技术
  • 基于STM32设计的智能台灯(腾讯云IOT)(234)
  • DataLight(V1.4.5) 版本更新,新增 Ranger、Solr
  • 匿名管道在进程池中的应用案例
  • 【学习笔记】MIPI
  • Linux驱动开发(速记版)--平台总线
  • Java NIO 全面详解:掌握 `Path` 和 `Files` 的一切
  • C语言 | Leetcode C语言题解之第435题无重叠区间
  • go语言 常用的web框架
  • hexo+github搭建个人博客
  • 2017年终总结、随想
  • Android单元测试 - 几个重要问题
  • Angular数据绑定机制
  • Bytom交易说明(账户管理模式)
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • isset在php5.6-和php7.0+的一些差异
  • Java应用性能调优
  • leetcode388. Longest Absolute File Path
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • magento2项目上线注意事项
  • mysql常用命令汇总
  • Python连接Oracle
  • Rancher如何对接Ceph-RBD块存储
  • react 代码优化(一) ——事件处理
  • Web标准制定过程
  • 阿里云前端周刊 - 第 26 期
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 分布式事物理论与实践
  • 和 || 运算
  • 开源地图数据可视化库——mapnik
  • 坑!为什么View.startAnimation不起作用?
  • 因为阿里,他们成了“杭漂”
  • 怎么把视频里的音乐提取出来
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​【已解决】npm install​卡主不动的情况
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • (NSDate) 时间 (time )比较
  • (pojstep1.1.2)2654(直叙式模拟)
  • (ZT)出版业改革:该死的死,该生的生
  • (六)vue-router+UI组件库
  • (算法设计与分析)第一章算法概述-习题
  • (一) springboot详细介绍
  • (一)appium-desktop定位元素原理
  • (一)kafka实战——kafka源码编译启动
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)ORM
  • (转)Scala的“=”符号简介
  • (转)VC++中ondraw在什么时候调用的