力扣热题100题-回文链表


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

示例 1:

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

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

提示:

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

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

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

解法1:没有参考解法,最粗糙的解答方法:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    //最初想到的方案:
    //时间复杂度 :o(n) 空间复杂度 o(n)
    //
    public boolean isPalindrome(ListNode head) {
        //找到head的长度
        ListNode first = head;
        ListNode center = head;
        int length = 0;
        
        Stack<Integer> stack = new Stack<>();
        while(first != null){
            length++;
            stack.push(first.val);
            first=first.next;
        }

        int centerLength = length/2;

        int count = 0;
        //判断长度是偶数还是奇数
        boolean isOu = length%2 == 0;
        while(center != null){
            Integer temp = stack.pop();
            if(isOu && count >= centerLength){
                if(center.val != temp){
                    return false;
                }
            } else if(!isOu && count >= centerLength+1){
                if(center.val != temp){
                    return false;
                }
            }
            count++;
            center = center.next;
        }
        return stack.isEmpty();
    }
}

这里借助了额外的存储空间,所以空间复杂度是O(n),循环了两次所以时间复杂度是O(n)

那么我们想想怎么能够优化空间复杂度呢?

主要问题是怎么获取到中间节点

我们可以死记硬背住获取中间节点的方法:

ListNode center = head;
        ListNode fast = head;
        while(fast.next != null && fast.next.next != null){
            fast = fast.next.next;
            center = center.next;
        }

如果已知中间节点,那就可以将中间节点之前的链表翻转,再跟中间节点之后的链表对比,就可以了。

好了,现在的问题简化为链表翻转问题。

public ListNode reverseList(ListNode head){
        ListNode reverse = null;
        while(head != null){
            ListNode temp = head;
            head = head.next;
            temp.next = reverse;
            reverse = temp;
        }
        return reverse;
    }

那最后可以得出解法:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {

        //得到中间节点
        ListNode center = head;
        ListNode fast = head;
        while(fast.next != null && fast.next.next != null){
            fast = fast.next.next;
            center = center.next;
        }

        //链表翻转
        ListNode reverse = reverseList(center);

        //判断节点是否相同
        while(head != null && reverse != null){
            if(head.val != reverse.val){
                return false;
            }
            head = head.next;
            reverse = reverse.next;
        }
        return true;
    }

    public ListNode reverseList(ListNode head){
        ListNode reverse = null;
        while(head != null){
            ListNode temp = head;
            head = head.next;
            temp.next = reverse;
            reverse = temp;
        }
        return reverse;
    }
}

时间复杂度为O(n) 空间复杂度为O(1)


文章作者: 冯廷鑫
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 冯廷鑫 !
  目录