leetcode234-回文链表

一.题目描述

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

示例 1:

输入: 1->2
输出: false
示例 2:

输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

二.题目解析

public static boolean isPalindrome(ListNode head) {
        /*暴力法遍历+栈,时间复杂度O(n),空间复杂度O(n)
        * */
        ListNode p1 = head,p2 = head;
        int count = 0;
        Stack<ListNode> stack = new Stack<>();
        //统计出所有的节点数
        while (p2 != null){
            count++;
            p2 = p2.next;
        }
        //前半部分压栈
        for (int i = 0; i < count / 2; i++) {
            stack.push(p1);
            p1 = p1.next;
        }
        //如果是奇数个节点就跳过中间那个节点
        if(count % 2 == 1){
            p1 = p1.next;
        }
        //弹栈依次比较
        while (!stack.isEmpty() && p1 != null){
            if(stack.pop().val != p1.val){
                return false;
            }
            //p1指针顺序往后遍历
            p1 = p1.next;
        }
        //经过上述处理两边的数量一定是相等的,故最后直接return true即可
        return true;
    }

在这里插入图片描述
2.

    ListNode left;
    boolean isPalindrome2(ListNode head) {
        /*递归,时间复杂度O(n),空间复杂度O(n)
        递归过程中实际上也相当于把节点压栈,不过这个栈指的是递归函数的堆栈
        eg.1->2->2->1  压栈顺序:traverse(1)->traverse(2)->traverse(2)->traverse(1)
        left按照顺序遍历的顺序,在弹栈的过程中right指针等同于逆序遍历的效果,二者再相比。
        * */
        left = head;
        return traverse(head);
    }

    boolean traverse(ListNode right) {
        if (right == null) return true;
        boolean res = traverse(right.next);
        // 此轮结果=前轮结果&&此轮两个对称的元素比较的结果
        res = res && (right.val == left.val);
        //left指针顺序往后
        left = left.next;
        return res;
    }

在这里插入图片描述

public static boolean isPalindrome1(ListNode head) {
        /*快慢指针法,时间复杂度 O(N),空间复杂度 O(1)
         * */
        ListNode fast = head,slow = head;
        //slow最终指向位置即为终点位置
        while (fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        //如果链表长度是奇数个,slow还需要前进一位
        if(fast != null){
            slow = slow.next;
        }
        ListNode newHead = null;
        //翻转从slow开始的部分
        slow = reverse(slow);
        //fast重新指向链表头
        fast = head;
        //前半部分和翻转后的后半部分依次比较
        while (slow != null){
            if(fast.val != slow.val){
                return false;
            }
            fast = fast.next;
            slow = slow.next;
        }
        return true;
    }

    private static ListNode reverse(ListNode slow) {
        /*翻转从slow开始的部分
        * */
        ListNode cur = slow,nextCur = null,prev = null;
        while (cur != null){
            //记录下个要处理的节点
            nextCur = cur.next;
            //实现翻转
            cur.next = prev;
            //更新prev
            prev = cur;
            //更新要处理的节点
            cur = nextCur;
        }
        return prev;
    }

在这里插入图片描述

注:类似于二叉树,

void traverse(TreeNode root) {
    // 前序遍历代码
    traverse(root.left);
    // 中序遍历代码
    traverse(root.right);
    // 后序遍历代码
}

链表也有前序和后序遍历

模板如下:

void traverse(ListNode head) {
    // 前序遍历代码
    traverse(head.next);
    // 后序遍历代码
}

参考文章:
https://labuladong.gitbook.io/algo/mu-lu-ye-1/mu-lu-ye/pan-duan-hui-wen-lian-biao

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值