IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 算法基础(九)– 回文链表 -> 正文阅读

[数据结构与算法]算法基础(九)– 回文链表

  1. 回文链表

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

示例 1:
pal1

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

示例 2:
pal2

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

提示:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list

解法描述

  1. 遍历链表,依次将每个元素放入栈中,然后重新从头结点遍历,与栈中弹出元素比对是否相等,完全相等则为回文结构;
  2. 在方法1基础上进行优化,栈中不必保存所有元素,只需定位到链表中点,然后将后续元素放入栈中,再从头结点(与栈中弹出元素)开始比对;
  3. 不使用栈结构来实现:首先还是定位到链表的中点或上中间(偶数个节点情况下定位中间两个节点的上一个)结点,然后将中间结点后面的链表元素改变指针方向,中点或上中间结点的元素next指向null,最后,头结点指针与尾结点指针同时向中间遍历,比较各个元素是否相等。
    最最后,不要忘记改变会原链表的指向。。

编码实现

方法1:

public boolean isPalindrome(ListNode head) {
    Stack<ListNode> stack = new Stack<>();
    ListNode cur = head;
    while (cur != null) {
        stack.push(cur);
        cur = cur.next;
    }

    ListNode pop;
    while (!stack.isEmpty()) {
        pop = stack.pop();
        if (pop.val != head.val) {
            return false;
        }
        head = head.next;
    }
    return true;
}

方法2

public boolean isPalindrome(ListNode head) {
    // 0 或 1个元素时,直接返回true
    if (head == null || head.next == null) {
        return true;
    }

    // 定位 下中点 或 中点下一个
    ListNode midOrDown = head.next;
    ListNode fast = head;
    // 2  s=2, f=1
    // 3  s=3, f=3
    // 4  s=3, f=3
    // 5  s=4, f=5
    while (fast.next != null && fast.next.next != null) {
        midOrDown = midOrDown.next;
        fast = fast.next.next;
    }
    
    Stack<ListNode> stack = new Stack<>();
    ListNode cur = midOrDown;
    while (cur != null) {
        stack.push(cur);
        cur = cur.next;
    }

    while (!stack.isEmpty()) {
        ListNode pop = stack.pop();
        if (pop.val != head.val) {
            return false;
        }
        head = head.next;
    }

    return true;
}

方法3

public boolean isPalindrome(ListNode head) {
    // 0 或 1个元素时,直接返回true
    if (head == null || head.next == null) {
        return true;
    }

    // 定位 上中点 或 中点
    ListNode midOrUp = head;
    ListNode fast = head;
    // 2  s=1, f=1
    // 3  s=2, f=3
    // 4  s=2, f=3
    // 5  s=3, f=5
    while (fast.next != null && fast.next.next != null) {
        midOrUp = midOrUp.next;
        fast = fast.next.next;
    }

    ListNode cur = midOrUp.next;
    midOrUp.next = null;

    // 链表后半部分反转
    ListNode pre = midOrUp;
    ListNode next;
    while (cur != null) {
        next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }

    ListNode last = pre;
    // 开始比对
    cur = pre;
    ListNode left = head;
    boolean res = true;
    while (left != null && cur != null) {
        if (left.val != cur.val) {
            res = false;
            break;
        }
        left = left.next;
        cur = cur.next;
    }

    // 恢复链表
    pre = null;
    cur = last;
    while (cur != null) {
        next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }

    return res;
}

复杂度分析

三种实现方法,时间复杂度上都是O(N),空间复杂度上有所不同:

  • 方法一将所有元素放入栈结构中,空间复杂度为O(N);
  • 方法二在方法一基础上进行了优化,空间复杂度为O(N/2)
  • 方法三则舍弃了栈结构,直接通过改变链表连接方向实现,空间复杂度为O(1),但要注意,方法三结束之前,需要改变回原来的链表连接方向!

实际使用时,我可能更倾向于使用方法二(在元素不多的情况下),毕竟方法三实现起来较为复杂,同时还要改变原来的机构,虽然最后会恢复原状,但需要注意很多细节。你更喜欢哪种方案呢?

欢迎关注我的公众号【CoolWrite】,了解更多内容:
我的公众号

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-13 13:06:58  更:2021-12-13 13:09:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:37:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码