【LeetCode】234. 回文链表

发布于:2024-08-13 ⋅ 阅读:(134) ⋅ 点赞:(0)

回文链表

题目描述:

        给你一个单链表的头节点 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) 空间复杂度解决此题?

方法一思路分析:

反转链表的一半

  1. 使用快慢指针找到链表的中点:快指针每次移动两步,慢指针每次移动一步,当快指针到达链表末尾时,慢指针就位于链表的中点(对于奇数个节点的链表,慢指针位于中间两个节点的第一个)。

  2. 反转链表的后半部分:从慢指针开始,反转链表的后半部分。

  3. 比较前后两部分:将反转后的后半部分与原始链表的前半部分进行比较,如果每个节点都相等,则是回文链表。

代码实现:

public class Solution {  
    public boolean isPalindrome(ListNode head) {  
        // 如果链表为空或只有一个节点,直接返回true  
        if (head == null || head.next == null) {  
            return true;  
        }  
  
        // 使用快慢指针找到链表的中点  
        ListNode slow = head;  
        ListNode fast = head;  
        ListNode prev = null;  
  
        while (fast != null && fast.next != null) {  
            prev = slow;  
            slow = slow.next;  
            fast = fast.next.next;  
        }  
  
        // 如果链表长度为奇数,则跳过中点  
        if (fast != null) {  
            slow = slow.next;  
        }  
  
        // 反转链表的后半部分  
        ListNode secondHalfHead = reverseList(slow);  
  
        // 比较前半部分和反转后的后半部分  
        ListNode p1 = head;  
        ListNode p2 = secondHalfHead;  
  
        while (p2 != null) {  
            if (p1.val != p2.val) {  
                return false;  
            }  
            p1 = p1.next;  
            p2 = p2.next;  
        }  
  
        return true;  
    }  
  
    // 反转链表的方法  
    private ListNode reverseList(ListNode head) {  
        ListNode prev = null;  
        ListNode curr = head;  
        while (curr != null) {  
            ListNode nextTemp = curr.next;  
            curr.next = prev;  
            prev = curr;  
            curr = nextTemp;  
        }  
        return prev;  
    }  
}

方法二思路分析:使用栈

        遍历链表,将遍历到的每个节点的值压入栈中。然后,再次遍历链表,同时从栈中弹出元素,比较从链表中取出的元素和从栈中弹出的元素是否相等。如果所有元素都匹配,则链表是回文的。

public class Solution {  
    public boolean isPalindrome(ListNode head) {  
        Stack<Integer> stack = new Stack<>();  
        ListNode curr = head;  
  
        // 遍历链表,将值压入栈  
        while (curr != null) {  
            stack.push(curr.val);  
            curr = curr.next;  
        }  
  
        // 再次遍历链表,同时从栈中弹出元素进行比较  
        curr = head;  
        while (curr != null) {  
            if (curr.val != stack.pop()) {  
                return false;  
            }  
            curr = curr.next;  
        }  
  
        return true;  
    }  
}

方法三思路分析:使用数组

        遍历链表,将遍历到的每个节点的值存储在一个数组中。然后,使用双指针技术(一个从头开始,一个从尾开始)来比较数组中的元素。这种方法的空间复杂度是O(n),其中n是链表的长度。

public class Solution {  
    public boolean isPalindrome(ListNode head) {  
        List<Integer> vals = new ArrayList<>();  
        ListNode curr = head;  
  
        // 遍历链表,将值存储在数组中  
        while (curr != null) {  
            vals.add(curr.val);  
            curr = curr.next;  
        }  
  
        // 使用双指针比较数组中的元素  
        int i = 0, j = vals.size() - 1;  
        while (i < j) {  
            if (!vals.get(i).equals(vals.get(j))) {  
                return false;  
            }  
            i++;  
            j--;  
        }  
  
        return true;  
    }  
}

网站公告

今日签到

点亮在社区的每一天
去签到