单链表的换头问题

如果涉及到单链表的相关算法题中涉及到换头操作,方法需要返回值

简单问题一

打印两个有序链表的公共部分

问题二

判断一个链表是否为回文结构
【题目】给定一个单链表的头节点head,请判断该链表是否为回文结构。
【例子】1->2->1,返回true;1->2->2->1,返回true;15->6->15,返回true;1->2->3,返回false。
【例子】如果链表长度为N,时间复杂度达到0(N),额外空间复杂度达到0(1)。

解析:
什么是链表的会问结构?
链表正着和反过来是一样的

方法一:使用栈(实现较为简单,但是只推荐在笔试中使用,面试中不推荐)

算法思想:借助栈进行实现,即将链表的元素依次进栈。全部进栈之后,由于栈先进后出的性质,栈顶的元素即为原链表中的最后一个值,然后和链表指针的移动同步依次出栈,比较每个元素,如果都相同,则肯定是回文的。这样做明显时间和空间复杂度:O(N)。具体代码如下:

package ListNode;
import Pojo.ListNode;
class MyList{public static ListNode head;public MyList(){this.head=null;}public static void main(String[] args) {int arr[] = {10, 5, 6, 8, 1, 8, 6, 5, 10};MyList my = new MyList();// 采用头插法建立单链表for (int i =0; i < arr.length; i++)my.addLast(arr[i]);my.display();boolean a=my.isPalindrome(head, arr.length);if(a==true){System.out.println("是回文结构");}else{System.out.println("不是回文结构");}}//尾插法建立单链表public void addLast(int data){ListNode node=new ListNode(data);if(this.head==null){this.head=node;}else {ListNode cur = this.head;while (cur.next != null) {cur = cur.next;}cur.next=node;}//return head;}// 使用栈空间进行链表的回文结构判断,时间和空间复杂度均为O(n)public boolean isPalindrome(ListNode node, int n){ListNode listNode = node;if (listNode == null || listNode.next.next == null)return false;// 创建一个临时栈空间ListNode[] temp_stack = new ListNode[n];int i = -1;// 所有结点入栈while (listNode != null){temp_stack[++i] = listNode;listNode = listNode.next;}// 遍历单链表,与对应的栈顶结点一一比较;但是要注意加上一个node.next结点不为空的条件,如果node.next为空,则停止遍历while (node.equals(temp_stack[i--]) && node.next != null)node = node.next;// 遍历完成后,如果单链表的下一个节点为空if (node.next == null)return true;return false;}//打印单链表public void display(){ListNode cur=head;while(cur!=null){System.out.print(cur.data+" ");cur=cur.next;}System.out.println();}
}

同时利用快慢指针和栈以减少空间复杂度

此时空间复杂度为O(n / 2),时间复杂度为O(n)

    // 使用快慢指针的方法实现回文结构的判断,这样能够做到空间复杂度为O(1)public boolean isPalindrome2(ListNode node, int n) {if (node == null || node.next.next == null)return false;ListNode fast = node;ListNode slow = node;// 这样对于单链表,当结点个数为奇数时,slow会走到中间位置;当结点个数为偶数时,slow结点处于链表的前一半的末尾位置。// 这种写法很巧妙while (fast.next.next != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}// 创建一个临时栈空间ListNode[] temp_stack = new ListNode[n / 2];int j = -1;ListNode mid = slow.next;while (slow.next != null){temp_stack[++j] = slow.next;System.out.println( temp_stack[j].data);slow = slow.next;}ListNode start = node;// 栈中存储的结点随着链表的遍历而出战,随后一一对比while (start.data == temp_stack[j--].data){// 遍历结束的一个条件,if (start.next == mid || start.next.next == mid) return true;start = start.next;}return false;}

利用快慢指针实现(只提供方法快慢指针的方法,其他的数据结构参考上文即可)

此算法的时间复杂度为O(n),空间复杂度为O(1),三种方法中,此种方法最优

步骤:
(1)利用快慢指针,分别为fast和slow每一次遍历,快指针走两步,慢指针走一步,快指针走到链尾时,慢指针出于中间的位置(如果链表长度为奇数,则处于正中间,下标为n/2,如果为偶数,下标为n/2 - 1;
(2)将右半部分链表的结点进行逆置操作,生成一个新的链表,但是左链表和右链表中的链尾都为slow结点,获取右链表的尾部结点
(3)同时遍历左链表和右链表,并且比较两者的的data域,如果有一处不相等,则执行return false。如果全部相等,则return true;但遍历的时候要考虑单双结点数的情况。
(4)可以考虑在返回之前,将链表还原

 // 使用快慢指针的方法实现回文结构的判断,这样能够做到空间复杂度为O(1)public boolean isPalindrome_usePointer(ListNode node, int n){if (node == null || node.next.next == null)return false;ListNode fast = node;ListNode slow = node;// 这样对于单链表,当结点个数为奇数时,slow会走到中间位置;当结点个数为偶数时,slow结点处于链表的前一半的末尾位置。while (fast.next != null && fast != null){slow = slow.next;fast = fast.next.next;}/* // 这段代码有问题,即使执行了后面的while循环,打印后仍然显示p.next = null;ListNode finalNode = new ListNode(111);// 反转slow开始的链表结点,ListNode p = slow;p.next = null;while (slow.next != null){System.out.println(" ----------------------- ");System.out.println(slow.data);ListNode q = slow.next;q.next = p.next;p.next = q;slow = slow.next;}*/ListNode p = slow.next;ListNode record_mid = slow;// 经历完以下的遍历,p结点的next域为空,slow处于最后一个结点位置while (p != null){ListNode pnext = p.next;// 使用链表进行反转p.next = slow;// 对下一个结点进行反转操作slow = p;p = pnext;}ListNode q = slow; // save last nodeq.next = null;// 这一行代码不能少,因为原来的链表中最后一个结点的next域为空,但是在链表反转的过程中,slow的next域指向了倒数第二个结点ListNode start = node;// slow往左遍历,node往右遍历,直到相遇,若其中存在两者对应的结点值不同的情况,返回falsewhile (slow != start){if (slow.data != start.data)return false;// 结点数为偶数时,slow和node结点相遇的情况不同的情况if (slow.next == start)return true;start = start.next; // start moveslow = slow.next; // slow move}// 方便后面再将该链表的右半部分逆序回来ListNode prev_q = q.next; // save the previous node of the last node// 返回之前,不要忘记把这个链表的右半部分逆序回来while (prev_q != record_mid){ListNode qnext = prev_q.next;// 实现结点逆转prev_q.next = q;q = prev_q;prev_q = qnext;}return true;}

链表的回文结构(算法笔记)相关推荐

  1. 左程云算法笔记(四)哈希表和有序表的使用、链表

    左程云算法笔记(四) 哈希表的使用 有序表的使用 链表 单链表反转 (LC206) 双向链表反转 打印两个有序链表的公共部分 合并两个有序链表(LC21) 判断一个链表是否为回文结构 (LC234) ...

  2. 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...

    来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...

  3. 《算法笔记》之链表二叉树

    链表 之前找工作的时候,受益于算法笔记,这次开始复习,也是从这本书入手,打算重新学习算法,因此从最基础的开始,只要我们去一点一点付出,最后一定结果不会差.加油,道虽远,行将就至. 链表有若干个节点组成 ...

  4. 算法笔记-链相关、链的基础、单链双链环链、链的各种功能实现、链的算法题、面试题以及算法优化方法(多)、C#

    1. 链定义及其基础 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.这组存储单元既可以是连续的,也可以是不连续的. 链表定义: 链表是一种线性表数据结构: 从底层存储 ...

  5. 数据结构与算法笔记(十五)—— 散列(哈希表)

    一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...

  6. 《algorithm-note》算法笔记中文版正式发布!

    无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...

  7. 【算法】《algorithm-note》算法笔记中文版正式发布!

    无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...

  8. 算法笔记(JavaScript版)——排序

    算法笔记(JavaScript版)--排序 本文内容根据Rebert Sedgewick和Kevin Wayne的<算法(第四版)>整理,原代码为java语言,自己修改为JavaScrip ...

  9. 算法笔记(胡凡)学习笔记@Kaysen

    本文旨在记录算法笔记学习过程中的收获和一些知识点,部分易错知识点只针对个人而言,CCF-CSP考试冲鸭!!! Chapter 2 C/C++快速入门(易错知识点) 2.1 基本数据类型 变量定义注意区 ...

最新文章

  1. (C#) GDI+简单绘图画直线
  2. 【Eclipse】推荐UML插件Green UML、AmaterasUML
  3. 函数组:SPO1/2/3/4/5/6/8
  4. setTimeout 和 setInterval
  5. 新建maven(servlet项目) 引入不了HttpServlet
  6. 【NOI2009】诗人小G【决策单调性dp】
  7. 技能学习重要的古语_学习方法:最重要的开发人员技能
  8. java 每隔一小时运行_每隔一小时执行一次 Full GC 分析排查
  9. LeetCode 139. 单词拆分(动态规划)
  10. 在Windows上使用Mingw-W64进行C/C++开发(gcc工具链)
  11. 四川大学计算机徐教授,我院举行“BIM实验室开放+徐教授专题讲座”活动
  12. Pygame制作音乐播放器
  13. 在Qt中设置程序图标的方法介绍
  14. Skywalking Ⅱ
  15. 腾讯和蘑菇街的面试总结
  16. Tossing Bad Mupd Msg Pid In The Alert.Log
  17. 司法背记一表通(吐血整理!!)
  18. [软件评测第九期]蚁丘保卫战(Anthi…
  19. duet连win10_duet display windows
  20. 计算机人体学,计算机人体工程学指南

热门文章

  1. 正则表达式验证校验邮箱的格式
  2. Java 面向对象综合案例
  3. Keil 5 编译报错FCARM - Output Name not specified, please check ‘Options for Target - Utilities‘
  4. 华为交换机堆叠如何进行主备倒换
  5. 【python】使用xlwt、xlrd、xlutils、openpyxl操作excel
  6. vue 实现canvas绘制地图,引用图片,对画布进行原点 滚轮缩放,按键缩放,拖动等功能 把pagex转化为offsetx
  7. 一篇文章带你搞定 HTTPS
  8. python3数据存储—四个数据库(sqlite,mysql,redis,mongodb)
  9. 面向对象-1-类和对象、基础语法、初始化、内置方法和属性
  10. 群组测试(Group testing)介绍