算法笔记一 链表的翻转(C++)
一 两两交换链表的节点
问题具体见Leecode 算法练习24题
1.1问题分析
1.1.1非递归法
对于非递归的方法我们主要分为四个步骤
1.新建一个节点tamp,让这个节点的next指向头节点
2.申明三个指针 ,前一个节点指针prev指向tamp , 当前节点指针cur指向head节点和下一个节点指针Next指向head的下一个节点。
3.让tamp的next域指向Next,让cur指针的next域指向Next节点的下一个节点,最后让Next节点的next域指向cur,交换后为0->2->1->3->4 ;
4.令prev指针等于cur节点 , cur指针等于cur->next , Next 指针等于cur->next
最后不断重复2,3,4三个步骤,直到cur指针为NULL或者cur指向NULL结束最后返回tamp节点的next域就是交换后的链表的头结点
具体参见下图
根据上面的解析代码如下:
class Solution {public:ListNode* swapPairs(ListNode* head) {ListNode*tamp = new ListNode(0) ;ListNode*pre = tamp ;tamp->next = head ;ListNode*cur = head ;while(cur != NULL){ListNode*Next = cur->next ;if(Next == NULL)break ;//***这三个交换的顺序一定不能调换pre->next = Next ;cur->next = Next->next ;Next->next = cur ;pre = cur ;cur = cur->next ;}return tamp->next ;}
};
对于链表类的题目还是要多动手在纸上画一画,这样会比较清楚。
1.1.2 递归法
由于链表的天然属性 ,我们很容易联想到递归,同时用递归的解决链表的一些题目也很方便。下面讲解一下递归的思路。
对于递归问题,我们所要做的就是从一个比较小的问题去推出大的问题。这里我们可以把任何一个要进行交换的链表的看成有三个节点构成的链表。即
head->Next->剩余部分,剩余部分是已经调整好顺序的。对于递归函数我们不需要知道他是怎么具体实现函数功能的,我们只要知道他的作用。在这个问题中我们的递归函数的作用是返回已调整好顺序的链表的头指针。这样我们就需要三步;
第一步 :让head.next = 剩余部分的头指针 。
第二步:让Next.next= head;
第三步:返回调整好顺序的链表的头指针;
这个递归的出口就是当head为空或者head的next域为空时就要停止递归。
具体的代码如下:
class Solution {public:ListNode* swapPairs(ListNode* head) { if(head == NULL || head->next ==NULL) //递归的出口return head ;ListNode *Next = head->next ; //取出Next节点head->next = swapPairs(Next->next) ; //head的next域指向已调整好顺序的链表的头结点Next->next = head ; //Next指向head return Next ;}
};
具体递归过程如图:
二 K个一组翻转
2.1问题
具体见lLeetCode链表题25
2.2 迭代法
对于K个一组进行翻转我们首先需要判断链表的长度是否大于k,若果不满足就返回头结点。若果满足就翻转,然后让翻转后的链表的最后一个节点指向第K+1个节点。然后在重复上面的步骤。
首先我们分析一下k个节点一组进行翻转,我们定义一个哑结点dummy,让他指向head,定义一个前一个节点指针prev, 当前节点指针cur, 下一个节点指针Next 。那么我们翻转的过程就是;第一步 初始化三个节点 dummy->next = head ; prev= dummy ; cur= head; Next= cur->next ; 第二步:
cur->next = dummy ; prev = cur ; cur = Next ; Next = cur->next ;最后重复上面的步骤直到cur= NULL;在吧头结点prev 返回具体的过程见下图
有了上面的分析代码也就很容易了
//k个链表短翻转ListNode *reverse(ListNode *head){ListNode *dummy = new ListNode(0) ; //申明一个哑结点dummy->next = head ; //哑结点的next域指向头结点ListNode *prev = dummy ;ListNode *cur = dummy->next ;while(cur !=NULL){ListNode *Next = cur->next ;cur->next = prev ;prev = cur ;cur = Next ;}return prev ;}
看懂了上面的分析,下面来分析一个链表,每k个一组翻转的解法。对于一个链表k个一组进行翻转我们,需要定义一个哑结点dummy ,前一个节点指针prev ,开始翻转的节点指针star, 翻转的最后一个节点指针end。dummy->next = head , prev = dummy , star = head , end = dummy。首先要判断链表长度是否大于k,若果不满足直接返回头节点。若果满足我们就去遍历找到第k+1个节点,作为下一个k个一组翻转的头节点,我们让prev->next 等于k翻转的头结点。然后让start->next = end->next ;也就是开始第二个k个节点的翻转的初始化,让prev = star , end= star, star= end->next ;直到end-next = NULL ;
具体的代码如下
ListNode* reverseKGroup(ListNode* head, int k) {ListNode *dummy = new ListNode(0) ; //申明一个哑结点dummy->next = head ; //哑结点指向头结点ListNode *prev = dummy ; //当前指针指向哑结点ListNode *start = head ; //开始指针指向头结点ListNode *end = dummy ; //结束指针指向哑结点while(end ->next!=NULL) //判断是否到达链表的尾部{for(int i = 0 ; i < k && end!=NULL ; i++) //找到第k个节点end = end->next ;if(end == NULL) //若果不够k个节点break ;ListNode *Next = end->next ; //下一个k个节点的开始end->next = NULL; //给翻转k个的链表一个结束prev->next = reverse(start) ; //让哑结点指向翻转后的头结点start->next = Next ; //给下一个k个翻转链表初始化prev = start ;end = start ;start = Next ; }return dummy->next ;}
2.3递归法
递归法我们要从一个小的问题,引出大的问题。这里我们可以把一个链表看成是有k个节点待翻转的链表和已经翻转完成的链表。这样我们只需把k个链表翻转一下,再连接到已经翻转完成的链表就行了。那个我们可以令翻转链表的函数返回翻转完成后的链表的表头。然后我们让前面k个节点的链表的链表头的next域指向翻转完成的链表的头节点,在不剩余的节点翻转完成即可。递归函数还有一个很重要的一点,就是递归的出口。在这个问题中我们可以看到递归的出口是待翻转的链表不过k个节点。具体的过程见下图。
由上面的知识我们可以写出代码如下:
class Solution {public:ListNode* reverseKGroup(ListNode* head, int k) {if(head == NULL) //判断是否为空节点return NULL ;ListNode *cur = head ;int i ;for( i = 0 ; i <k && cur != NULL ; i++)cur = cur->next ;if(i != k) //判断是否有k个节点return head ;ListNode *prev = reverseKGroup(cur , k) ; //将未排好序的头节点指向已排好序的链表头结点cur = head ;while(k > 0) //用迭代法将k个节点翻转{ListNode *tamp = cur->next ;cur->next = prev ;prev = cur ;cur = tamp ;k-- ;}return prev ;}
};
做链表相关的题目,一定要多去画画图,很多东西当你画一些图后就会比较清晰。
算法笔记一 链表的翻转(C++)相关推荐
- 算法笔记-经典链表操作案例
单链表反转 链表中环的检测 两个有序的链表合并 删除链表倒数第 n 个结点 求链表的中间结点 <?php /*** User: lide01* Date: 2018/10/9 14:06* De ...
- 算法笔记-判断链表保存的字符串是否是回文
<?php/*** 单链表节点** Class SingleLinkedListNode** @package Algo_06*/ class SingleLinkedListNode {/** ...
- [算法笔记]-环形链表Ⅱ-解题方法
原题链接:https://leetcode-cn.com/problems/linked-list-cycle-ii/ Given a linked list, return the node whe ...
- 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...
来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...
- 左程云算法笔记(四)哈希表和有序表的使用、链表
左程云算法笔记(四) 哈希表的使用 有序表的使用 链表 单链表反转 (LC206) 双向链表反转 打印两个有序链表的公共部分 合并两个有序链表(LC21) 判断一个链表是否为回文结构 (LC234) ...
- 《算法笔记》之链表二叉树
链表 之前找工作的时候,受益于算法笔记,这次开始复习,也是从这本书入手,打算重新学习算法,因此从最基础的开始,只要我们去一点一点付出,最后一定结果不会差.加油,道虽远,行将就至. 链表有若干个节点组成 ...
- 【算法笔记】极客时间 算法面试通关40讲 笔记 覃超
[算法笔记]极客时间 算法面试通关40讲 覃超 [算法笔记]极客时间 算法面试通关40讲 覃超 相关链接 在leetcode 上的题号 数组.链表: (堆)栈stack.队列queue 优先队列 哈希 ...
- 算法笔记知识点整理大全
每次刷题都觉得自己吃了知识点不全,基础不牢固的亏,刷题的时候目标也不明确,于是看完了算法笔记并把知识点归纳了一下,当然直接看书会更加详细,这个归纳只是学习时加深印象以及方便自己之后回顾而已:之后刷题大 ...
- 算法笔记——每日一题(完结)
算法笔记 From Now To My Death 前言 初级算法 1.两数之和 7.整数反转 9.回文数 14.最长公共前缀 27.移除元素[拷贝复制] 28.实现strStr()[双指针] 35. ...
最新文章
- 除了eWTP试验区,阿里云还要在马来西亚部署全球第15座数据中心
- HashMap解决hash冲突的方法
- Jscript 内部对象
- 【312】◀▶ arcpy 常用函数说明
- 移动互联网APP测试流程及测试点(转载)(一)
- html pre标签增加行号,vue使用highlight.js 添加行号
- vsftp匿名访问目录_怎么更改vsftp匿名用户的默认登录目录/var/ftp?
- java gui变量_关于java:静态/类变量和GUI
- el表达式/jstl保留两位小数
- CentOS7发布ASP.NET Core网站
- 怎么把AI文件导入到PS里面
- NLP学习04--长短期记忆网络LSTM
- 开源分词系统pkuseg学习
- php 将rgb转cmyk,将CMYK颜色值和RGB颜色相互转换的PHP代码
- 【吴恩达】机器学习第16章异常检测以及ex8部分编程练习
- PX4飞控学习与开发(六)-利用 VScode 修改源码
- 模式识别与机器学习(PATTERNnbsp;RECO…
- mysq coun(*)时为啥这么慢
- cad拉伸怎么用_【cad比例缩放教程】cad缩放怎么用?
- linux中的硬盘分区和挂载