Loading

回文链表

1.问题描述

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

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

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

2.求解

存储到数组中使用双指针判断

  • 遍历整个链表把所有的值存储到list集合中
  • 设置指针i,j分别从头部和尾部对比是否相同

代码如下

/*
 *执执行用时:4 ms, 在所有 Java 提交中击败了28.12% 的用户
 * 内存消耗:42.2 MB, 在所有 Java 提交中击败了40.65% 的用户
 * */
public boolean isPalindrome(ListNode head) {
    if (head == null) {
        return true;
    }
    List<Integer> list = new ArrayList<>();
    while (head != null) {
        list.add(head.val);
        head = head.next;
    }
    int i = 0, j = list.size() - 1;
    while (i < j) {
        if (!list.get(i).equals(list.get(j))) {
            return false;
        }
        i++;
        j--;
    }
    return true;
}
  • 当然在这里用list数组只是一种方法,也可以使用栈这一结构来进行比较

递归

递归比较难以理解,可以先借助下面这个例子理解,如何使用递归倒序打印一个链表

代码如下

public class Solution {
    int i = 0;
    void printNode(ListNode head){
        if(head == null){
            return;
        }
        printNode(head.next);
        i++;
        System.out.println("我是倒数第" + i + "个节点,我的值是:" + head.val);
    }
}
  • 在这段代码中,我们把自增的i换成我们需要比较的节点就可以求出题目的答案

代码如下

/*
 * 执行用时:3 ms, 在所有 Java 提交中击败了33.88% 的用户
 * 内存消耗:44.5 MB, 在所有 Java 提交中击败了5.00% 的用户
 * */
ListNode temp;
public boolean isPalindrome2(ListNode head) {
    temp = head;
    return check(head);
}

public boolean check(ListNode head) {
    if (head == null) {
        return true;
    }
    boolean ans = (check(head.next) && head.val == temp.val);
    temp = temp.next;
    return ans;
}
  • 在方法外面定义全局变量temp,这个temp相当于我们上文中的i
  • 递的过程先拿到链表的最后一个节点,然后开始归的过程,用最后一个节点与temp比较,用倒数第二个节点与temp.next比较,以此类推

反转链表后半部分

在方法1和方法2中我们无论如何都做不到O(1)的空间复杂度,要想满足O(1)的空间复杂度,我们可以使用反转后半部分链表来对比的方法

代码如下

/*
 * 执行用时:1 ms, 在所有 Java 提交中击败了99.86% 的用户
 * 内存消耗:40.9 MB, 在所有 Java 提交中击败了96.45% 的用户
 * */
public boolean isPalindrome3(ListNode head) {
    ListNode fast = head, slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
    }
    if (fast != null) {
        slow = slow.next;
    }
    slow = reverse(slow);
    while (slow != null) {
        if (slow.val != head.val) {
            return false;
        }
        slow = slow.next;
        head = head.next;
    }
    return true;
}

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

ps:如何使用递归反转链表
剑指 Offer-反转链表的3种方式

posted @ 2020-10-23 15:53  水纸杯  阅读(76)  评论(0)    收藏  举报