HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

    • 【中级】12k-26k档

      • JVM进阶

      • Java进阶

      • MySQL

      • 中间件

      • 算法

        • 1-两数之和
        • 高频算法面试题
        • 2两数相加
        • 09-用两个栈实现一个队列
        • 11-盛水最多的容器
        • 19-删除链表的倒数第N个结点
        • 20-有效的括号
        • 22-括号生成
        • 39-组合总和
        • 46-全排列
        • 53-连续最大子序和
        • 64匹马,只有8个赛道,挑选出最快的4匹马
        • 70-爬楼梯
        • 136-只出现一次的数字
        • 141环形链表
        • 206-翻转链表
        • 234回文链表
        • 387-字符串中的第一个唯一字符
        • 543二叉树最大直径
        • 八大排序算法
        • 剪绳子
        • 旋转数
        • 模板
        • 求解立方根不使用库函数
      • 高阶

    • 【高级】26k+档

    • 大厂面试题

    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 【中级】12k-26k档
  • 算法
#回文链表
码农阿雨
2022-06-02
目录

234回文链表

# 描述

难度:简单

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

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

进阶: 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/palindrome-linked-list 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

# 思路

# 方法一 :辅助栈、hashmap、数组、Map

字符串回文大家都知道怎么做了,这里也一样可以用数组、List、HashMap、栈去存放节点的值,然后遍历前半部分,和后后半部分逐一进行比较。

这种方法比较简单,但是 时间复杂度是 O(2N) 和 空间复杂度是 O(N)

# 方法二:反转链表

可以将后半部分链表反转,或者把后半部分的值入栈。

你需要先了解反转链表的实现,用到了双指针:206-翻转链表

步骤是:

  1. 找到中点,可以利用双指针,慢指针走1步,快指针走2步,快指针走到尾部NULL,那么慢指针刚好就走到了中点
  2. 反转中点.next 之后(也就是后半部分)的链表。
  3. 前半部分链表和反转的后半部分链表 进行比较。

见代码。

# 题解

public class 回文链表234 {
    static class ListNode {
        int val;
        ListNode next;
        ListNode(int x) {
            val = x;
            next = null;
        }
    }

    public static void main(String[] args) {
        ListNode listNode = new ListNode(1);
        listNode.next = new ListNode(2);
        listNode.next.next = new ListNode(3);
        listNode.next.next.next = new ListNode(2);
        listNode.next.next.next.next = new ListNode(1);
        System.out.println(isPalindrome(listNode));
        System.out.println(isPalindrome2(listNode));
        System.out.println(isPalindrome3(listNode));
    }

    /**
     * 辅助Map,当然放在List也一样
     * 时间复杂度 O(2N)
     * 空间复杂度 O(N)
     *
     * @param head
     * @return
     */
    static boolean isPalindrome(ListNode head) {
        if (head == null) {
            return false;
        }
        Map map = new HashMap<Integer, Integer>();
        int i = 0;
        while (head != null) {
            map.put(i++, head.val);
            head = head.next;
        }
        for (int j = 0; j < map.size() / 2; j++) {
            if (map.get(j) != map.get(map.size() - j - 1)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 辅助栈
     *
     * @param head
     * @return
     */
    static boolean isPalindrome2(ListNode head) {
        //面腾讯遇到了这道题,当时想到用的栈,回来看发现之前没这么做过,来做一做
        LinkedList<Integer> stack = new LinkedList<Integer>();
        ListNode tmp = head;
        //把全部节点的值入栈
        while (tmp != null) {
            stack.push(tmp.val);
            tmp = tmp.next;
        }
        //传递一个指针到tmp2,指向head头部
        ListNode tmp2 = head;
        while (tmp2 != null) {
            if (tmp2.val != stack.pop()) {
                return false;
            }
            tmp2 = tmp2.next;
        }
        return true;
    }

    /**
     * 翻转后半部分的链表
     * @param head
     * @return
     */
    static boolean isPalindrome3(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 static 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 static 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;
    }
}
阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#回文链表
上次更新: 2026-03-28 17:00:16
最近更新
01
MySQL支持的锁有哪些
03-28
02
HTTP 是不保存状态的协议, 如何保存用户状态
03-28
03
用户态和内核态的区别
03-28
更多文章>
Theme by Vdoing | Copyright © 2020-2026 码农阿雨
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式