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

数据结构——单链表OJ题(上)

目录

一、移除链表元素

1.思路

2.注意

3.解题

二、反转链表

思路1:三指针翻转法

(1)注意

(2)解题

思路2:头插法

(1)注意

(2)解题

三、链表的中间结点

思路1:快慢指针法

(1)注意

(2)解题 

思路2:两次遍历法

(1)注意

(2)解题

四、返回倒数第k个结点

1.思路:快慢指针法

2.注意

3.解题

五、合并两个有序链表

1.思路

2.注意

3.解题

六、链表分割

1.思路

2.注意

3.解题

七、写在最后

 


一、移除链表元素

1.思路

创建一个新链表,用指针pcur遍历原链表,对每个结点的数据进行判断,如果等于val则不做处理,如果不相等则尾插到新链表中。

2.注意

(1)原链表可能为空,那么返回NULL;

(2)最后记得将newTail指向NULL,在此之前需要判断newTail不能为空,因为如果为空,不存在newTail->next。

3.解题

typedef struct ListNode ListNode;
struct ListNode*removeElements(ListNode* head , int val)
{if(head == NULL)//传入的该链表可能为空{return NULL;}//创建一个新链表ListNode* newHead = NULL;ListNode* newTail = NULL;//创建一个遍历该链表的指针ListNode* pcur = head;while(pcur){if(pcur->val != val){如果不等于val,尾插到新链表中if(newHead == NULL){newHead = newTail = pcur;}else{newTail->next = pcur;newTail = newTail->next;}}pcur = pcur->next;}//将尾结点指向NULLif(newTail){newTail->next = NULL;}return newHead;
}

二、反转链表

思路1:三指针翻转法

创建三个指针n1,n2,n3分别指向NULL、head和head->next,改变指向,将n2指向n1,进行循环遍历原链表。

(1)注意

①原链表可能为空,那么返回NULL;

②n1为反转链表的头结点。

(2)解题

typedef struct ListNode ListNode;
ListNode* reverseList(ListNode* head)
{if(head == NULL){return NULL;}ListNode *n1,*n2,*n3;n1 = NULL;n2 = head;n3 = head->next;while(n2){n2->next = n1;n1 = n2;n2 = n3;if(n3){n3 = n3->next;}}return n1;
}

思路2:头插法

创建新链表,通过pcur遍历原链表,将数据头插到原链表中,得到反转链表。

(1)注意

①创建新指针保存pcur的下一个结点,否则pcur无法找到原位置。

(2)解题

typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head)
{//新链表ListNode* newhead = NULL;ListNode* pcur = head;while(pcur){//保存当前结点的下一个结点ListNode* next = pcur->next;//头插新结点pcur->next = newhead;//更新头结点newhead = pcur;//移动到下一个结点pcur = next;}return newhead;
}

三、链表的中间结点

思路1:快慢指针法

初始时,快指针和慢指针都指向头结点。快指针一次经过两个结点,慢指针一次经过一个节点,当快指针走到链表结尾时,慢指针指向链表中间。

(1)注意

①分别分析一下链表长度为奇数和偶数时的情况(具体在代码中);

②最后返回指向链表中间的指针slow。

(2)解题 

typedef struct ListNode ListNode;
ListNode* middleNode(ListNode* head)
{ListNode* fast = head;ListNode* slow = head;while(fast && fast->next)//由于fast->next要取next,因此不能为空//且不能交换顺序:否则链表长度为偶数的情况不能实现{fast = fast->next->next;slow = slow->next;}return slow;
}

思路2:两次遍历法

第一次遍历得到链表的长度len,由此得到半个长度mid,第二次遍历得到中间结点。

(1)注意

①mid为len/2+1(len为int类型);

②在第二个while循环中,pcur初始为head,每进行一次循环pcur就指向下一个结点。因此,当mid写为len/2,那么在第二次循环中就顺利可实现。

(2)解题

typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) 
{ListNode* pcur = head;int len = 0;//遍历得到链表的长度lenwhile(pcur){len++;pcur = pcur->next;}int mid = len / 2 ;//让pcur遍历链表,得到中间结点pcur = head;while(mid--){pcur = pcur->next;}return pcur;
}

四、返回倒数第k个结点

1.思路:快慢指针法

初始时,快指针和慢指针都指向头结点。快指针先走k步,然后快、慢指针同时走,当快指针走到链表末尾时,慢指针走到倒数第k个结点。

2.注意

①返回的是倒数第k个结点保存的数据,而非指针;

②若k大于链表长度,fast会为空,此时返回NULL。

3.解题

typedef struct ListNode ListNode;
int kthToLast(struct ListNode* head, int k)
{ListNode* fast = head;ListNode* slow = head;while(k--){if(fast){fast = fast->next;}else {return NULL;}}while(fast){fast = fast->next;slow = slow->next;}return slow->val;
}

五、合并两个有序链表

1.思路

创建两个指针分别遍历两个链表,比较两个指针指向结点存储的数据,创建新链表,将小的数据存储在新链表中。

2.注意

①使用malloc创建非空链表,在尾插数据时不再需要判断newHead是否为NULL,避免代码冗余;

②当n1和n2其中一个为空会跳出循环,说明遍历完成。此时需要将另外一个尾插到新链表中。

③不必再令newTail指向空,因为此时尾结点不是newTail,而是后续尾插的n1或n2。

3.解题

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}//创建新链表ListNode* newHead, *newTail;newHead = newTail = (ListNode*)malloc(sizeof(ListNode));ListNode* n1 = list1;ListNode* n2 = list2;while(n1 && n2){if(n1->val < n2->val){newTail->next = n1;newTail = newTail->next;n1 = n1->next;}else{newTail->next = n2;newTail = newTail->next;n2 = n2->next;}}if(n1){newTail->next = n1;}if(n2){newTail->next = n2;}ListNode* ret = newHead->next;free(newHead);newHead = NULL;return ret;
}

六、链表分割

1.思路

创建两个新链表(大于x和小于x的分别存储在两个链表中),用pcur遍历原链表,最后将大链表尾插在小链表后。

2.注意

①使用malloc创建两个非空链表,分别存储大于和小于x的数据。

3.解题

typedef struct ListNode ListNode;
ListNode* partition(ListNode* pHead, int x) {//大链表ListNode* greaterHead, *greaterTail;greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));//小链表ListNode* lessHead,*lessTail;lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));ListNode* pcur = pHead;while(pcur){if(pcur->val < x){lessTail->next = pcur;lessTail = lessTail->next;}else {greaterTail->next = pcur;greaterTail = greaterTail->next;}pcur = pcur->next;}lessTail->next = greaterHead->next;greaterTail->next = NULL;ListNode* ret = lessHead->next;free(lessHead);free(greaterHead);lessHead = greaterHead = NULL;return ret;}

七、写在最后

一起加油,敬请期待“单链表OJ题(下)”~

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 玄机-第一章 应急响应-webshell查杀
  • 数据库之数据表基本操作
  • Prometheus监控ZooKeeper
  • Matlab arrayfun 与 bsxfun——提高编程效率的利器!
  • exuberant ctags 支持 typescript 解析
  • 自动驾驶-机器人-slam-定位面经和面试知识系列05之常考公式推导(02)
  • 什么是埋点?前端如何埋点?
  • 速盾:分享一些防御 DDoS 攻击的措施
  • 爬虫 APP 逆向 ---> 粉笔考研
  • 请你谈谈:spring bean的生命周期 - 阶段5:BeanPostProcessor前置处理-自定义初始化逻辑-BeanPostProcess后置处理
  • Profinet从站转TCP/IP协议转化网关(功能与配置)
  • 使用DuiLib进行UI开发的虚函数解析及控件绑定、响应与消息处理
  • selenium----CSS表达式选择元素
  • PDF解锁网站
  • 数据库DDL | 增 删 改 操作 | 对数据库数据表
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Android优雅地处理按钮重复点击
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • JavaScript设计模式与开发实践系列之策略模式
  • Leetcode 27 Remove Element
  • LeetCode18.四数之和 JavaScript
  • maya建模与骨骼动画快速实现人工鱼
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • PHP面试之三:MySQL数据库
  • Redash本地开发环境搭建
  • SQLServer之创建显式事务
  • underscore源码剖析之整体架构
  • web标准化(下)
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 对超线程几个不同角度的解释
  • 普通函数和构造函数的区别
  • 首页查询功能的一次实现过程
  • 详解NodeJs流之一
  • 一份游戏开发学习路线
  • 一起参Ember.js讨论、问答社区。
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 在weex里面使用chart图表
  • - 转 Ext2.0 form使用实例
  • 7行Python代码的人脸识别
  • (07)Hive——窗口函数详解
  • (10)ATF MMU转换表
  • (c语言)strcpy函数用法
  • (void) (_x == _y)的作用
  • (四)库存超卖案例实战——优化redis分布式锁
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)甲方乙方——赵民谈找工作
  • (转载)Google Chrome调试JS
  • (状压dp)uva 10817 Headmaster's Headache
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .JPG图片,各种压缩率下的文件尺寸
  • .NET 4.0中的泛型协变和反变
  • .Net CF下精确的计时器
  • .NET Core中的去虚