(链表)LC回文链表

题目

在这里插入图片描述

方法一:使用栈记录遍历节点,再比较

栈有先进后出的特点,遍历一遍链表,依次入栈;再遍历一遍链表并依次对栈进行弹栈操作并比较是否满足回文要求

public boolean isPalindrome(ListNode head) {

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

    }
  • 时间复杂度:需要两次遍历链表,时间复杂度为O(2n)=O(n)
  • 空间复杂度:需要额外的栈空间存储遍历的节点信息,O(n)

方法二:转为数组,使用双指针比较

遍历一遍链表,将其转为一个数组,就可以使用首指针和尾指针依次像中间遍历比较

public boolean isPalindrome(ListNode head) {
        List<ListNode> list = new ArrayList<>();
        ListNode tmp = head;
        while(tmp != null){
            list.add(tmp);
            tmp = tmp.next;
        }
        int i = 0 , j = list.size() - 1;
        while(i < j){
            if(list.get(i++).val != list.get(j--).val)
                return false;
        }
        return true;

    }
  • 时间复杂度:需要遍历一遍链表和一遍数组,时间复杂度为O(2n)=O(n)
  • 空间复杂度:需要额外的数组空间,O(n)

方法三:翻转半段比较

使用快慢指针的方式,找到链表的中间节点,即快指针走两步,慢指针走一步,当快指针到尾部的时候,慢指针即指向中间位置。

找到中间位置后,将后半段的链表进行翻转操作,再依次遍历前半段和后半段,比较相应的节点。

public boolean isPalindrome(ListNode head) {
        if(head == null)
            return true;
        // 中间节点
        ListNode midNode = getMidNode(head);
        // 翻转后半段
        ListNode rightHead = reverse(midNode.next);
        ListNode tmpI = head , tmpJ = rightHead;
        boolean rs = true;
        while(tmpJ != null){
            if(tmpI.val != tmpJ.val){
                rs = false;
                break;
            }
            tmpI = tmpI.next;
            tmpJ = tmpJ.next;
        }
        // 还原
        reverse(rightHead);
        return rs;
    }

    /**
     * 获得中间节点
     * @param head
     * @return
     */
    public ListNode getMidNode(ListNode head){
        if(head == null || head.next == null)
            return head;
        ListNode fast = head , slow = head;
        while(fast.next != null){
            fast = fast.next;
            if(fast.next != null){
                fast = fast.next;
                slow = slow.next;
            }
        }
        return slow;
    }

    /**
     * 翻转链表
     * @param head
     * @return
     */
    public ListNode reverse(ListNode head){
        if(head == null || head.next == null)
            return head;
        ListNode newHead = head , tmp;
        while(head.next != null){
            tmp = head.next;
            head.next = tmp.next;
            tmp.next = newHead;
            newHead = tmp;
        }
        return newHead;
    }
  • 时间复杂度:找到中间节点需要遍历一遍链表,O(n),翻转后半段需要O(n),比较是否为回文需要O(n),总复杂度为O(n)
  • 空间复杂度:不需要额外的存储空间,为O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值