力扣-234-回文链表

news2024/12/22 20:47:53

回文链表

CategoryDifficultyLikesDislikes
algorithmsEasy (52.70%)1576-
Tags

Companies


给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

示例 1:

img

输入:head = [1,2,2,1]
输出:true

示例 2:

img

输入:head = [1,2]
输出:false

提示:

  • 链表中节点数目在范围[1, 105]
  • 0 <= Node.val <= 9

知识点补充:

  1. 有两种常用的列表实现,分别为数组和链表。
    1. 数组列表底层是使用数组存储值,可以通过索引再O(1)的时间内访问列表的任何位置的值,这是由基于内存寻址的方式。
    2. 链表存储的是称为节点的对象,每个节点保存一个值和指向下一个节点的指针。访问某个特定索引的节点需要O(n)的时间,因为要通过指针获取到下一个位置的节点。
  2. 确定数组列表是否为回文很简单,可以使用双指针来比较两端的元素,并向中间移动,而将链表的值赋值到数组列表中是O(n),因此最简单的方法就是将链表的值复制到数组列表中,再使用双指针法判断。

思路

  1. 看了网上很多双指针,数组,栈,哈希算法计算的,都觉得大题小作了,一下看到一个让人眼前一亮的方法,记录一下。

    1. 就是通过StringBuilder类,将链表中的值存储再一个StringBuilder中,然后使用equals方法计算stringBuilder和stringBuilder.resverse()的值,结果就是答案。

      class Solution {
          public boolean isPalindrome(ListNode head) {
              StringBuilder stringBuilder = new StringBuilder();
              while (head != null) {
                  stringBuilder.append(head.val);
                  head = head.next;
              }
              return stringBuilder.toString().equals(stringBuilder.reverse().toString());
          }
      }
      
  2. 虽然按照上述问题能解决,但是还是得看一下使用不同的算法实现的方式。

    1. 将head链表的值存储在数组中,然后判断。

      class Solution {
          public boolean isPalindrome(ListNode head) {
              List<Integer> vals = new ArrayList<Integer>();
              // 将链表的值复制到数组中
              ListNode currentNode = head;
              while (currentNode != null) {
                  vals.add(currentNode.val);
                  currentNode = currentNode.next;
              }
              // 使用双指针判断是否为回文数
              int front = 0;
              int back = vals.size() - 1;
              while (front < back) {
                  if (!vals.get(front).equals(vals.get(back))) {
                      return false;
                  }
                  front++;
                  back--;
              }
              return true;
          }
      }
      
  3. 递归的方法

    1. 如果使用递归反向迭代节点,同时使用递归函数外的变量向前迭代,就可以判断链表是否为回文。

    2. 指针是先到尾节点,由于递归的特性再从前往后进行比较。frontPointer是递归方法外的指针。若currentNode.val != frontPoint.val 则返回false。反之,frontPinter向前移动并返回true。

    3. 算法的正确性在于递归处理节点的顺序是相反的(回顾上面打印的算法),而我们再函数外又记录了一个变量,因此从本质上,我们同时在正向和逆向迭代匹配。

      class Solution {
          private ListNode frontPointer;
      
          private boolean recursivelyCheck(ListNode currentNode) {
              if (currentNode != null) {
                  if (!recursivelyCheck(currentNode.next)) {
                      return false;
                  }
                  if (currentNode.val != frontPointer.val) {
                      return false;
                  }
                  frontPointer = frontPointer.next;
              }
              return true;
          }
      
          public boolean isPalindrome(ListNode head) {
              frontPointer = head;
              return recursivelyCheck(head);
          }
      }
      
  4. 快慢指针

    1. 可以将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。比较完成后我们应该将链表回复原样。

    2. 步骤:

      1. 找到前半部分链表的尾节点。
      2. 反转后半部分链表。
      3. 判断是否为回文。
      4. 恢复链表。
      5. 返回结果。
    3. 可以根据快慢指针进行判断,找到中间值(前半部分链表的尾节点)。

      class Solution {
          public boolean isPalindrome(ListNode head) {
              if (head == null) {
                  return true;
              }
              // 找到前半部分链表的尾节点
              ListNode firstHalfEnd = endOfFirstHalf(head);
              ListNode secondHalfStart = reverseList(firstHalfEnd.next);
              // 判断是否为回文
              ListNode p1 = head;
              ListNode p2 = secondHalfStart;
              boolean 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;
          }
      
          private ListNode reverseList(ListNode head) {
              ListNode prev = null;
              ListNode curr = head;
              while (curr != null) {
                  ListNode nextTemp = curr.next;
                  curr.next = prev;
                  prev = curr;
                  curr = nextTemp;
              }
              return prev;
          }
      
          private ListNode endOfFirstHalf(ListNode head) {
              ListNode fast = head;
              ListNode slow = head;
              while (fast.next != null && fast.next.next != null) {
                  fast = fast.next.next;
                  slow = slow.next;
              }
              return slow;
          }
      }
      
  5. 哈希法也是比较优秀的,这里复制粘贴代码,我觉得实现起来逻辑比较复杂,可能是还没太多关于哈希计算的知识点积累,后续再来回顾。

    class Solution {
        public boolean isPalindrome(ListNode head) {
            ListNode t=head;
    		int base = 11, mod = 1000000007;
        	int left = 0, right = 0, mul = 1;
            while(t!=null){
            	left = (int) (((long) left * base + t.val) % mod);
            	right = (int) ((right + (long) mul * t.val) % mod);
                mul = (int) ((long) mul * base % mod);
                t=t.next;
            }
            return left==right;
        }
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66419.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FTP文件传输服务

FTP 服务概述2-1 FTP连接及连接模式 控制连接&#xff1a;TCP 21&#xff0c;用于发送FTP命令信息 数据连接&#xff1a;TCP 20&#xff0c;用于上传、下载数据 数据连接的建立类型 主动模式&#xff1a;服务端从 20 端口主动向客户端发起连接 被动模式&#xff1a;服务端在指…

SIM8262E-M2,SIM8262A-M2,SIM8260C-M2,SIM8260C 5G定位模组支持多频段

SIM8262&#xff1a;支持R16标准的5G模组&#xff0c;支持多频段5G NR / LTE-FDD / LTE TDD / HSPA&#xff0c;支持SA和NSA双组网模式&#xff0c;高达 2.4Gbps的数据传输&#xff1b;扩展能力强&#xff0c;接口丰富&#xff0c;包括PCIe、USB3.1、GPIO等。该模块为客户的应用…

Polygon zkEVM中的子约束系统

1. 引言 前序博客有&#xff1a; Polygon zkEVM工具——PIL和CIRCOM Polygon zkEVM中主要设计了3种子约束系统&#xff1a; 1&#xff09;Permutation check子约束系统&#xff1a;PIL中的关键字为is。 2&#xff09;Plookup 子约束系统&#xff1a;PIL中的关键字为in。 …

数据结构——栈,队列,及其结构特点应用。

​✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;数据结构——栈&#xff0c;队列。 &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 ☂️<4>开发环境&#xff1a;Visual Studio 2022 &#x1f3e1;<5>系统环境…

路由查找原理

最近在设计Netflow采集系统时&#xff0c;我想要将客户端的公网IP根据IP库转为对应的国家&#xff0c;此外在CACHE机房中&#xff0c;交换机上是没有AS信息的&#xff0c;因此我们也需要根据IP去查路由库&#xff0c;转换出AS信息。 这两个问题的本质是类似的&#xff0c;无论是…

棱镜七彩作为首批成员单位入选工信部网络安全产业发展中心重点实验室!

近日&#xff0c;工信部网络安全产业发展中心公布了网络安全技术与产业发展工信部重点实验室专项工作组成员单位名单。棱镜七彩首批入选&#xff0c;成为信息技术应用创新基础软硬件安全工作组的成员单位&#xff01; 为深入贯彻落实网络强国战略&#xff0c;充分发挥网络安全技…

FOC控制之小A小B小C是如何追求小D的

1、写在前面 随着电动汽车的热火&#xff0c;关于FOC控制技术的文章这几年在网络上可谓是一搜一大把&#xff0c;各种理论分析&#xff0c;公式推导&#xff0c;应有尽有。通过这些文章&#xff0c;可以看出大佬还是很多的。另外也有FOC的开源硬件。而在大几年前&#xff0c;第…

党务管理系统搭建,答题获积分,学习有好礼

党务管理系统搭建是以服务党员群众为目的的&#xff0c;然后通过互联网信息化手段&#xff0c;将党建工作与大数据等新技术融合&#xff0c;实现党建资源答题学习的数字化整合&#xff0c;也提升了党建科学化水平。 党务管理系统搭建助力党建数字化、规范化&#xff1a;利用信息…

快来生成你专属的英文名吧(使用字符级RNN)!

目录 一.前言 二.准备数据 三.构造神经网络 四.训练 五.网络采样&#xff08;预测&#xff09; 一.前言 数据集为18个国家的姓氏&#xff0c;任务是根据训练得到的模型&#xff0c;在给定国家类别和首字母后&#xff0c;能得到一个与该国人名非常相似的一个人名。 > …

openstack基本命令小结

文章目录Openstack0、进入1、查看日志日志位置日志格式举例2、CLI命令格式基本格式使用帮助3、命令文档&#xff08;常用&#xff09;4、基础组件的常用命令1、keystone查询类查看所有组件状态查看所有服务的状态查看域列表查看服务列表查看节点列表查询用户列表查询用户详细信…

用5G制造5G,中国电信打造“滨江模式”,助力电子信息制造产业升级

工业和信息化部近日印发《5G全连接工厂建设指南》&#xff0c;提出“十四五”时期&#xff0c;主要面向原材料、装备、消费品、电子等制造业&#xff0c;采矿、港口、电力等重点行业领域&#xff0c;加快5G全连接工厂建设。中国电信联合中兴通讯打造南京滨江智能工厂&#xff0…

Python第三方库之MedPy

1.MedPy简介 MedPy 是一个图像处理库和针对医学(如高维)图像处理的脚本集合&#xff0c;此处主要讨论利用该库计算常见的医学图像分割任务评价指标&#xff0c;如Dice、Jaccard、Hausdorff Distance、Sensitivity、Specificity、Positive predictive value等。 论文表格的表头…

docker部署的redis集群 添加节点(扩容)

上篇博文完成了在 docker 中部署 redis 多主多从集群&#xff1a;点这里 这篇博文说一下如何在集群基础上继续添加节点&#xff0c;也就是给集群扩容 博文中的命令出现的 111.111.111.111 均换成实际 IP 执行 创建要添加的一主一从容器 这里创建一个6377主节点和一个6378从节…

ArgoDB 5.1 正式发布:多模融合、实时分析和数据安全多重升级

Transwarp ArgoDB是星环科技自主研发的高性能分布式分析型数据库&#xff0c;在PB级数据量上提供极致的数据分析能力。ArgoDB支持标准SQL语法和分布式事务&#xff0c;提供高并发高速数据写入、复杂查询、多模分析、数据联邦、隐私计算和动态脱敏等能力。基于星环科技ArgoDB数据…

怎么自由裁剪图片大小?分享一款在线图片编辑工具

工作的时候常常需要用图片编辑工具把图片裁剪为我们想要的大小&#xff0c;但下载处理图片软件又耗费时间&#xff0c;那么有没有比较快捷的修改图片的方法呢&#xff1f;其实我们可以用在线图片处理&#xff08;在线ps 图片编辑制作工具 免费照片编辑器_压缩图&#xff09;工具…

日期插件(默认显示当前日期)---年月

方法&#xff1a;加载页面时将当前日期赋值 <!-- 选择年月--> <div class"form-group"><label class"col-sm-2 control-label is-required">时间&#xff1a;</label><button id"bin0"><< </button&g…

Nvidia 驱动安装

由于使用unreal engine editor 开发,需要安装nvidia 独显驱动,遇到各种坑,在此记录,方便自己以后再次遇到,也希望能帮助他人辟坑 系统: Ubuntu18.04 显卡:Geforce GTX 1650 UE版本:5.1.0 1. 自动安装 sudo ubuntu-drivers devices 推荐安装470 sudo ubuntu-drivers autoi…

Redis哨兵模式原理剖析,监控、选主、通知客户端你真的懂了吗?

哨兵启动后只指定了master的地址&#xff0c;要想知道整个集群中完整的拓扑关系怎么做呢&#xff1f; 哨兵每隔10秒会向每个master节点发送 info 命令&#xff0c; info 命令返回的信息中&#xff0c;包含了主从拓扑关系&#xff0c;其中包括每个slave的地址和端口号。有了这些…

[附源码]计算机毕业设计汽配管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

10. 获取操作系统版本和位数

1. linux如何查看系统版本 (1) 查看系统版本&#xff1a;uname -a (2) 查看内核版本信息&#xff1a;less /proc/version (3) 查看发行版本信息&#xff1a;less /etc/issue (4) 查看发行版详细信息&#xff1a;lsb_release -a 2. 怎么查看linux是32位还是64 系统 (1) getco…