[算法]——链表(三)

[算法]——链表(三)

目录

​编辑

一、前言

二、正文

1.重排链表

1.1 题目解析

1.2 算法原理

1.3 具体代码

2.K个一组翻转链表

2.1 题目解析

2.2 算法原理

2.3 具体代码

三、结语


一、前言

        本文将继续为大家带来链表的学习!!!

二、正文

1.重排链表

1. 重排链表 - [力扣]

1.1 题目解析

        本题要求要求我们对所给链表进行重排,那么观察题目所给示例,我们会发现所谓重排后的链表,就是先头结点,尾结点,然后头结点的下一个节点,尾结点的前一个节点……y依次类推,直至链表所有的元素都被插入。

1.2 算法原理

         那么本题的原理依旧是模拟的思路,那么该如何模拟呢?

具体的步骤如下:

1.找到链表的中间节点——利用快慢双指针

2.根据快慢双指针将链表分为两部分,对slow指针后面的部分进行逆序(使用头插法),其目的是为了该部分插入的顺序与我们模拟的插入相同

3.合并两个链表——利用双指针

1.3 具体代码

/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: void reorderList(ListNode* head) { if(head->next==nullptr) return ; ListNode* ret=new ListNode; ListNode* back=new ListNode; //找到链表中的中间节点 ListNode *slow=head,*fast=head->next; while(fast->next && fast->next->next) { slow=slow->next; fast=fast->next->next; } //head-slow(前) slow->next-tail(后) //对后面的链表进行逆序 ListNode *cur=slow->next; while(cur) { ListNode* next=cur->next; if(back->next==nullptr) { back->next=cur; cur->next=nullptr; //不处理会导致死循环 } else { cur->next=back->next; back->next=cur; } cur=next; } //合并两个链表 slow->next=nullptr; ListNode *cur1=head,*cur2=back->next,*cur3=ret; while(cur1 && cur2) { cur3->next=cur1; cur1=cur1->next;//二三行不能颠倒, cur3=cur3->next; cur3->next=cur2; cur2=cur2->next; cur3=cur3->next; } while(cur2) { cur3->next=cur2; cur2=cur2->next; } head=ret->next; } };

2.K个一组翻转链表

2.1 题目解析

        本题与我们之前讲过的一题类似,不知道小伙伴们还记不记得“两两交换链表中的节点”那道题,那道题要求我们对来链表中的两两节点进行交换,而本题则是提升了一点难度,交换的节点个数为k个,对于不足k个节点则不用进行交换

2.2 算法原理

        本题的算法思路依旧是模拟,即模拟题目交换节点的过程

具体步骤如下:

1.求出需要逆序的组数n

2.重复n次:长度为k的链表逆序

3.把不需要翻转的链表接在最后一次翻转的节点之后




注:这里要注意的一点在每次逆序结束之后,我们都要将prev节点重新调整位置至下一次要逆序的第一个节点的前一个,即我们本次逆序链表的首个插入节点

2.3 具体代码

/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* reverseKGroup(ListNode* head, int k) { //1.求出需要逆序的组数 ListNode* cur = head; int n = 0; while (cur) { n++; cur = cur->next; } n/=k; //2.重复n次:长度为k的链表逆序 ListNode* newhead = new ListNode(0); ListNode* prev = newhead; cur = head; for(int i=0;i < n;++i) { ListNode* tmp=cur; for(int j=0;j<k;j++) { ListNode* next = cur->next; cur->next = prev->next; prev->next = cur; cur = next; } prev=tmp; } //把不需要翻转的接上 prev->next = cur; return newhead->next; } };

三、结语

         到此为止,本文关于链表(三)内容到此结束了,如有不足之处,欢迎小伙伴们指出呀!

         关注我 _麦麦_分享更多干货:_麦麦_-ZEEKLOG博客

         大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下期见!

        欢迎大家参观我的算法专栏:

麦麦的算法专栏https://blog.ZEEKLOG.net/m0_73953114/category_12866812.html

Read more

.net Core Web 保姆级教学 逐文件讲解 从0搭建一个 ASP.NET Core Razor Pages

我们可以把整个项目比喻成一家餐厅的运作体系。 第一步:先看项目结构(以默认模板为例) 当你通过 Visual Studio 或 dotnet new webapp 命令创建一个新项目后,会看到类似下面的文件夹和文件(不同版本可能略有差异,但核心一致): 你的项目名称/ │ ├── 📁 Properties/ │ └── launchSettings.json (配置文件:启动按钮的设置) │ ├── 📁 wwwroot/ (餐厅的"公共用餐区":存放浏览器能直接访问的静态文件) │ ├── 📁 css/ (样式文件 - 餐厅的装修风格) │ ├── 📁 js/ (JavaScript文件 - 服务员的现场互动) │ └── 📁 lib/ (第三方库 - 比如借来的桌椅餐具) │ ├── 📁 Pages/ (餐厅的"核心包间区":所有网页都在这里) │ ├── 📁 Shared/ (公共组件:每个包间都有的墙壁、菜单样式) │ │ └── _Layout.

By Ne0inhk
【从零开始学数据结构①】:顺序表

【从零开始学数据结构①】:顺序表

学完c语言的基础语法,我们便要开始数据结构的学习,那么什么是数据结构呢,听我给你一一道来吧! 一.数据结构 1.什么是数据结构? 定义:数据结构是计算机存储、组织数据的方式。 2.为什么要使用数据结构? 在前面几章中我们学习到了数组这一概念,用下标来管理数据,但是你有没有想过,如果数据量过大,仅用数组便于管理和使用吗? 显然有些吃力了,那么这里便是为什么使用数据结构的原因了,以结构的形式进行数据管理。 二.顺序表 1.线性表 在了解顺序表前先让大家了解一下线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中广泛使⽤的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。 2.顺序表的定义 顺序表是一种线性表的顺序存储结构,底层结构为数组,

By Ne0inhk

LeetCode 11 - 盛最多水的容器

思路 容器面积由 宽度 和 短板高度 决定。最优解一定藏在不断收窄宽度的过程中。 1. 初始化:left 指针在数组头部,right 指针在尾部。这是最宽的可能。 2. 移动策略:比较 height[left] 和 height[right]。 * 面积受限于短板。若移动长板,宽度变小,高度不变(或变小),面积必然减小。 * 因此,必须移动短板对应的指针。这虽然牺牲了宽度,但给了我们寻找更高板子的机会,面积才有可能增大。 3. 迭代:循环此过程,持续更新最大面积,直到两指针相遇。 C++ 代码实现 classSolution{public:intmaxArea(vector<int>& height){int

By Ne0inhk
【数据结构指南】深入二叉树遍历

【数据结构指南】深入二叉树遍历

前言:         在前文中,我们探讨了完全二叉树和满二叉树的概念与性质,并基于完全二叉树实现了堆这一数据结构。然而,对于普通二叉树的认识仍有待深入,本文将系统性地介绍普通二叉树的遍历相关内容。                   一、前置说明          一般而言,对于一棵普通二叉树是通过链式结构定义,即每个节点包含三个部分:          1.数据域(data):用于存储节点的值          2.左指针(left):用于指向左子节点          3.右指针(right):用于指向右子节点                  typedef int BTDataType;//此处将 (int)整形 作为节点存储的内容 typedef struct BinaryTree { BTDataType data; struct BinaryTree* left; struct BinaryTree* right; }BTNode;                  在学习二叉树的基本操作前,需先要先创建一棵二叉树,然后才能学习

By Ne0inhk