目录

-数组法-

-递归法-

-快慢指针-


-题目-

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/bool isPalindrome(struct ListNode* head) {}

(注意:这题的条件为不带头结点的单链表,head就是链表的第一个结点)

(这里函数返回类型bool使用方法是直接返回false或者true。)

看到题目,博主第一想法就是头插法再建立一个链表,遍历两个链表就能得出该链表是否是回文的。但这个思路实现起来容易出错,以至于我改了n遍都没改对= =。

下面记录三个力扣官方给的三个思路(图片来源也是力扣官方)

-数组法-

将链表的值依次放进数组,再判断数组里的数是不是回文序列。

bool isPalindrome(struct ListNode* head){struct ListNode *p;int a[100000], i = 0;p = head;while(p){a[i++] = p -> val;p = p -> next;}int l = 0, r = i - 1;while(1){if(l >= r){break;}if(a[l] != a [r]){return false;}l ++;r --;}return true;
}

-递归法-

基本思路是创建两个指针:frontNode从前面开始遍历链表,currentNode从后面开始遍历链表。这个方法的思路不难理解,复杂的是currentNode通过递归调用函数来从链表尾开始往前遍历

struct ListNode* frontNode;bool recursivelyCheck(struct ListNode* currentNode) {if (currentNode != NULL) {if (!recursivelyCheck(currentNode -> next)) {return false;}if (currentNode -> val != frontNode -> val) {return false;}frontNode = frontNode -> next;}return true;
}bool isPalindrome(struct ListNode* head) {frontNode = head;return recursivelyCheck(head);
}

这里介绍一下currentNode实现其功能的过程

        这个过程涉及到栈,但是不用学到栈也能看懂,只需要知道栈是后进先出就行。

假设该链表存有五个数据5-6-1-7-5(不为回文序列),从主函数调用recursivelyCheck(head)开始,这一步将currentNode指向#0(这里用'#数字'来表示第几个结点)。currentNode不为null所以执行if,计算机确定了currentNode的下一个结点为#1,便将这个结点的值传入递归函数。(在调用函数前,计算机会将这个信息在栈中记录他在哪里)接下来再调用函数recursivelyCheck(#1)将currenyNode指向#1,同样的currentNode不为null所以执行if,计算机确定了currentNode的下一个结点为#2,再将其传入递归函数,再在栈中记录。再调用函数...

-信息在栈中存储的模式如下图-

(从recursivelyCheck(head)这一步开始入栈)

递归调用进行到recursivelyCheck(#4)时,currentNode仍不为null所以执行if,再下一步时递归进行到recursivelyCheck(NULL),因为链表里共有五个数,#4 -> next就是空指针NULL。此时if不执行,直接返回true给上一级。

这一级currentNode指向#4,!true为假故不返回flase,执行currentNode指向#4为5,frontPointer指向#0为5,两者相等故不返回false,然后frontPointer后移一个结点,来到最后一行代码,返回true给上一级。栈顶的信息移除 (如图,原本最顶端的信息移除)。

这一级currentNode指向#3,同样不返回false,执行currentNode指向#3为7,frontPointer指向#1为6,两者不相等故在这一步直接返回false给上一级。(可以知道若每一次currentNode和frontPointer都相等的话最后会返回true给原函数。

这一级currentNode指向#2, !false为真故直接返回false给上一级。从这以后就不用考虑两个指针的值了,因为false会被一层层返回给原函数。

 -快慢指针-

基本思路是将链表的后半部分反转,再比较前后两部分是否相同。

当然可以遍历链表得到链表长度,再取中间结点,但是这里使用了快慢指针的奇特方法。即创建快指针和慢指针,初始都指向head,慢指针每次移动一个结点,快指针每次移动两个结点直到快指针的下一次移动指向NULL,此时慢指针指向的结点就是中间结点。若链表结点为奇数个,易得中心结点不影响后续结果。

struct ListNode* reverseList(struct ListNode* head) {struct ListNode* prev = NULL;struct ListNode* curr = head;while (curr != NULL) {struct ListNode* nextTemp = curr->next;curr->next = prev;prev = curr;curr = nextTemp;}return prev;
}//三指针法反转链表struct ListNode* endOfFirstHalf(struct ListNode* head) {struct ListNode* fast = head;struct ListNode* slow = head;while (fast->next != NULL && fast->next->next != NULL) {fast = fast->next->next;slow = slow->next;}return slow;
}//使用快慢指针找到链表的中心位置bool isPalindrome(struct ListNode* head) {if (head == NULL) {return true;}// 找到前半部分链表的尾节点并反转后半部分链表struct ListNode* firstHalfEnd = endOfFirstHalf(head);struct ListNode* secondHalfStart = reverseList(firstHalfEnd->next);// 判断是否回文struct ListNode* p1 = head;struct ListNode* p2 = secondHalfStart;bool result = true;while (result && p2 != NULL) {if (p1->val != p2->val) {result = false;}p1 = p1->next;p2 = p2->next;}// 还原链表并返回结果firstHalfEnd->next = reverseList(secondHalfStart);return result;
}

时间复杂度与空间复杂度的控制是算法的精髓,上面三个方法有不同的时间,空间复杂度,因为博主这方面了解尚浅,故不在这里具体分析。

判断回文链表(剑指offer.027)相关推荐

  1. 从尾到头打印链表---剑指Offer

    从尾到头打印链表 输入一个链表,从尾到头打印链表每个节点的值. 解题思路: 1. 将带有头结点的链表顺序的从头到尾加入到ArrayList集合 2. 使用Collections工具类将ArrayLis ...

  2. 【博客搬家旧文】剑指offer [ java ] 面试题10 斐波那契数列

    契波那契数列最常见的解法,递归如下: public class Solution {public int Fibonacci(int n) {if(n == 0)return 0;else if(n ...

  3. asp 判断数组等于_剑指Offer(牛客版)--面试题4:二维数组中的查找

    SCDN博客:https://blog.csdn.net/weixin_41923658 微信公众号:「汤姆鱼」 -------------------------------------手动分割线- ...

  4. 3、从尾到头打印链表------------剑指offer系列

    题目 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 分析 要了解链表的数据结构: val属性存储当前的值,next属性存储下一个节点的引用. 要遍历链表就是不断找到当前节点的nex ...

  5. Java利用二维数组判断节假日_《剑指offer》面试题3 二维数组中的查找 Java版

    (二维数组,每行递增,每列递增.输入二维数组和一个整数,判断数组中是否含有此数.) 我的方法:拿到题目,根据题目条件我提取出这样一个特性:一个数的右边和下面的数都比它大.于是就可以写出一种递归的方法: ...

  6. 面试题5:从尾到头打印单链表(链表--剑指offer)

    题目描述 输入一个链表,从尾到头打印链表每个节点的值. //方法一:从头到尾打印单链表,将结果存放至vector中,然后将vector倒置 vector<int> printListFro ...

  7. Leetcode刷题笔记——剑指offer II (一)【整数、数组、字符串、链表】

    目录 整数 剑指 Offer II 001. 整数除法 剑指 Offer II 002. 二进制加法 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数 剑指 Offer II 00 ...

  8. 力扣OJ 剑指 Offer II

    目录 剑指 Offer II 001. 整数除法 剑指 Offer II 002. 二进制加法 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数 剑指 Offer II 004. ...

  9. 判断字符串_python实现--判断回文字符串、回文链表、回文数

    所谓回文字符串,就是正读和反读都一样的字符串,比如"level"或者"noon"等等就是回文串.即是对称结构Python系列教程,免费获取,遇到bug及时反馈, ...

最新文章

  1. 一个牛逼的 多级缓存 实现方案!
  2. 2004-5-12+ 用DataSet实现分页
  3. linux c++ 多进程初步01
  4. 设计模式_4_原型模式(对象的拷贝)
  5. linux安装mvn及nexus远程仓库
  6. wps linux 哪个版本好用吗,WPS Linux版与国产统一操作系统UOS完成适配:体验追上Wintel...
  7. javaee 学习书籍推荐
  8. 白帽子讲Web安全(一)浏览器安全
  9. 表达式的LenB(123程序设计ABC)的值是
  10. 免费稳定的APP分发托管平台,支持应用合并、内测分发、扫码下载
  11. 简简单单说外键和级联
  12. 碉堡了!最大 18 禁网站用 AI 和 ML 来做视频分类加标签
  13. kafka和raft共识机制
  14. flutter 状态管理 flutter_bloc 的使用以及总结
  15. clap与slap_slap-slap和clap有什么区别?slap和c – 手机爱问
  16. 通讯录中每个通讯者的信息包括编号、姓名、性别、电话、E-mail地址;采用单链表结构存储
  17. 利用C++创建一个游戏(9)愤怒的小鸟(代码+注释)
  18. python爬取知乎文章_Python爬取知乎日报,推送到kindle
  19. 某些有趣的API接口
  20. 养子女对养父母和亲生父母都要有赡养义务吗

热门文章

  1. python elasticsearch
  2. tensorflow 进阶(二),BP神经网络
  3. mysql第五章项目二_Todo List:Node+Express 搭建服务端毗邻Mysql – 第五章(第1节)
  4. 37. Leetcode 100. 相同的树 (二叉树-二叉树性质)
  5. (纯干货)万字长文,数据分析利器 pandas 全教程
  6. 来个邪恶假说,假如有人把支付宝所有存储服务器炸了,我们在里边的钱是不是都丢了?
  7. ClickHouse 在字节跳动广告场景的应用
  8. 【python进阶】_多线程多进程
  9. LeetCode-剑指 Offer 03. 数组中重复的数字
  10. 详解Numpy的广播机制