前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >如果我今天吃晚饭,就把我反过来!

如果我今天吃晚饭,就把我反过来!

作者头像
公众号袁厨的算法小屋
发布2020-11-25 09:41:17
发布2020-11-25 09:41:17
32100
代码可运行
举报
运行总次数:0
代码可运行

请判断一个链表是否为回文链表。

示例 1:

代码语言:javascript
代码运行次数:0
运行
复制
输入: 1->2
输出: false

示例 2:

代码语言:javascript
代码运行次数:0
运行
复制
输入: 1->2->2->1
输出: true

题目解析:

题目理解起来很简单,判断是否为回文,如果单纯判断一个字符串或者数组是不是回文很容易。但是题目中的链表为单链表,指针只能后移不能前移。所以我们判断起来会比较困难。而且这个题目若是想到了巧妙的方法,但是编码实现阶段或许仍会有些困难。

巧用数组法:

我们首先将链表的所有元素都保存在数组中,然后再利用双指针遍历数组,进而来判断是否为回文。这个方法很容易理解,而且代码实现也比较简单。

代码语言:javascript
代码运行次数:0
运行
复制
class Solution {
    public boolean isPalindrome(ListNode head) {
        //这里需要用动态数组,因为我们不知道链表的长度
        List<Integer> arr = new ArrayList<Integer>();
        ListNode copynode = head;
        //将链表的值复制到数组中
        while (copynode != null) {
            arr.add(copynode.val);
            copynode = copynode.next;
        }
        // 双指针遍历数组
        int back = 0;
        int pro = arr.size() - 1;
        while (back < pro) {
            //判断两个指针的值是否相等
            if (!arr.get(pro).equals(arr.get(back))) {
                return false;
            }
            //移动指针
            back++;
            pro--;
        }
        return true;
    }
}

这个方法可以直接通过,但是需要辅助数组,那我们还有其他更好的方法吗?

双指针翻转链表法

在上个题目中我们知道了如何找到链表的中间节点,那我们可以在找到中间节点之后,对后半部分进行翻转,翻转之后,重新遍历前半部分和后半部分进行判断是否为回文。

动图解析:

中间节点部分

翻转链表部分

代码语言:javascript
代码运行次数:0
运行
复制
class Solution {
    public boolean isPalindrome(ListNode head) {
         if(head==null||head.next==null){
              return true;
         }
         //找到中间节点,也就是翻转的头节点,这个在昨天的题目中讲到
         //但是今天和昨天有一些不一样的地方就是,如果有两个中间节点返回第一个,昨天的题目是第二个
         ListNode midenode =  searchmidnode(head);
         //原地翻转链表,需要两个辅助指针。这个也是面试题目,大家可以做一下,剑指offer244题,会发现很简单
         //这里我们用的是midnode.next需要注意,因为我们找到的是中点,但是我们翻转的是后半部分

         ListNode backhalf = reverse(midenode.next);
         //遍历两部分链表,判断值是否相等
         ListNode p1 = head;
         ListNode p2 = backhalf;         
         while (p2 != null) {
            if (p1.val != p2.val) {
               return false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }        
        // 还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文,
        //当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。
        midenode.next = reverse(backhalf);
        return true;       
    }
    //找到中间的部分
    public ListNode searchmidnode( ListNode head){       
          ListNode fast = new ListNode(-1);
          ListNode slow = new ListNode(-1);
          fast = head;
          slow = head;
          //找到中点
          while(fast.next!=null&&fast.next.next!=null){
              fast=fast.next.next;
              slow=slow.next;
          }       
          return slow;
    }
    //翻转链表
    public ListNode reverse(ListNode slow){
          ListNode low  = null;
          ListNode temp =null;
          //翻转链表
          while(slow!=null){
                  temp = slow.next;
                  slow.next = low;
                  low = slow;
                  slow = temp;
          }
          return low;
    }
}

题库里面的题,没有孤立存在的,或多或少都会与其他题目有所联系,所以刚开始刷题阶段不可以盲目刷题,这样会影响刷题效率。

题目来源:leetcode 234. 回文链表

大家如果觉得这篇文章对大家有帮助的话,就请你将它转发给需要的人吧,顺便请大家点个关注在看吧,创作不易。你们的支持对我真的帮助很大!每天都会为大家分享一道精选算法题,从简到难,我们一起坚持下去吧。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 袁厨的算法小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 巧用数组法:
  • 双指针翻转链表法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档