判断链表是否是回文结构(反转链表方式,栈的方式,栈的优化方式,原地比较的方式)

本文探讨了四种判断链表是否为回文结构的方法:通过反转链表、使用栈(空间复杂度O(N))、栈的优化(使用一半的存储空间)以及原地比较(空间复杂度O(1))。在栈优化方案中,找到链表中点,将后半部分元素入栈,与未入栈部分比较。原地比较则直接逆序链表的下半部分,与上半部分比较后再恢复链表原状。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反转链表的方式

这种方式比较简单,通过创建一个和原链表的逆序的方式,然后逐一进行比较;

boolean isPalindromeReverse(ListNode head){
        if(head == null) return false;
        ListNode cur = head;
        ListNode tmpHead = null;

        while(cur!= null) {
                ListNode tmp = new ListNode(cur.val);
                tmp.next = tmpHead;
                tmpHead = tmp;
                cur = cur.next;
        }
        cur = head;
        while(cur != null){
            if(cur.val != tmpHead.val) return false;
            cur = cur.next;
            tmpHead = tmpHead.next;
        }
        return true;
    }

栈方式(空间复杂度O(N))

1.利用栈的先进后出的特性,把所有的节点进行入栈,出队列是正好原链表的顺序相反,然后逐一比较

boolean isPalindromeStack(ListNode head) {
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode cur = head;
        while(cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        cur = head;
        while(!stack.isEmpty()) {
            ListNode tmp = stack.pop();
            if(tmp.val != cur.val) return false;
            cur = cur.next;
        }
        return true;
    }

栈方式优化(使用一半的存储空间)

1.首先找到链表的中点**(长度为奇数,中点,长度为偶数,取上中点)**
2.将除了中点的剩余元素都进入栈;(之所以这么操作,后半部分入栈,出栈时逆序,出栈时依次和栈的元素一次比较,恰好实现首尾比较)

//首先链表的中点,如果链表长度为奇数返回中点,如果是偶数返回上中点
    //然后将链表中点后元素都入栈的结构,
    //弹出栈中的元素分别和链表的元素比较
    private boolean isPalindromeOptimizeStack(ListNode head) {
        if (head == null) return false;
        if (head.next == null) return true;

        ListNode slow = head, fast = head.next;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode cur = slow.next;
        Stack<ListNode> stack = new Stack();

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

原地比较(空间复杂度O(1))

1.首先找到链表的中点**(长度为奇数,中点,长度为偶数,取上中点)**
2.这一步不是使用栈的结构实现逆序,而是进行链表的逆序;
3.以mid为起点,对之后的元素进行逆序;
4. 上半部分链表和下部分链表进行逐次比较
5. 对链表修改进行复原;

private boolean isPalindromeLinkedReverse(ListNode head) {
        if (head == null) return false;
        if (head.next == null) return true;
        //链表的中点
        ListNode midNode = getMidOrUpMidNode(head);
        //链表中点右侧的链表进行反转链表
        ListNode pre = midNode;
        ListNode curB = midNode.next, next = null;
        midNode.next = null; //断开链表
        while (curB != null) {
            next = curB.next;
            curB.next = pre;
            pre = curB;
            curB = next;
        }
        //pre执行头节点;
        curB = pre;
        //比较前后两部分链表元素是否是相等,判断是否是回文结构
        ListNode curA = head;
        while (curA != null && curB != null) {
            if (curA.val != curB.val) return false;
            curA = curA.next;
            curB = curB.next;
        }
        //恢复到原来的链表
        curB = pre;
        pre = null;
        while (curB != midNode) {
            next = curB.next;
            curB.next = pre;
            pre = curB;
            curB = next;
        }
        curB.next = pre;
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值