剑指 Offer II 027. 回文链表(234. 回文链表)

题目:

 

思路:

【1】使用快慢指针找出中间,进行反转后再比较的方式(因为如果复原的话,是需要考虑后面还会不会用,其实不会用的话不复原都是可以的,毕竟好多都是直接在上面空间进行修改来节省空间)

【2】将值复制到数组中后用双指针法(这种就类似于处理回文字符串了)

【3】使用递归的方式

代码展示:

使用递归的方式:

//时间16 ms击败18.10%
//内存58.4 MB击败19.79%
//时间复杂度:O(n),其中 n 指的是链表的大小。
//空间复杂度:O(n),其中 n 指的是链表的大小。
//因为在一个函数中调用一个函数时,计算机需要在进入被调用函数之前跟踪它在当前函数中的位置(以及任何局部变量的值),通过运行时存放在堆栈中来实现(堆栈帧),所以在使用递归时空间复杂度要考虑堆栈的使用情况。
class Solution {
    private ListNode frontPointer;

    private boolean recursivelyCheck(ListNode currentNode) {
        if (currentNode != null) {
            if (!recursivelyCheck(currentNode.next)) {
                return false;
            }
            if (currentNode.val != frontPointer.val) {
                return false;
            }
            frontPointer = frontPointer.next;
        }
        return true;
    }

    public boolean isPalindrome(ListNode head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }
}

 

将值复制到数组中后用双指针法的方式:

//时间8 ms击败41.19%
//内存53.4 MB击败83.27%
class Solution {
    public boolean isPalindrome(ListNode head) {
        List<Integer> vals = new ArrayList<Integer>();

        // 将链表的值复制到数组中
        ListNode currentNode = head;
        while (currentNode != null) {
            vals.add(currentNode.val);
            currentNode = currentNode.next;
        }

        // 使用双指针判断是否回文
        int front = 0;
        int back = vals.size() - 1;
        while (front < back) {
            if (!vals.get(front).equals(vals.get(back))) {
                return false;
            }
            front++;
            back--;
        }
        return true;
    }
}

 

使用快慢指针找出中间,进行反转后再比较的方式:

不对原本链表进行复原:

//时间3 ms击败99.58%
//内存58.2 MB击败21.20%
//时间复杂度:O(n),其中 n 指的是链表的大小。
//空间复杂度:O(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 {
    public boolean isPalindrome(ListNode head) {
        ListNode pre = null;
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            ListNode temp = slow.next;
            if(pre != null) {
                slow.next = pre;
            }
            pre = slow;
            fast = fast.next.next;
            slow = temp;
        }
        if(fast != null) slow = slow.next;
        while(slow != null){
            if(slow.val != pre.val) return false;
            slow = slow.next;
            pre = pre.next;
        }
        return true;
    }
}

 

对原本链表进行复原:

//时间5 ms击败62.82%
//内存51.3 MB击败97.25%
class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null) {
            return true;
        }

        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode firstHalfEnd = endOfFirstHalf(head);
        ListNode secondHalfStart = reverseList(firstHalfEnd.next);

        // 判断是否回文
        ListNode p1 = head;
        ListNode p2 = secondHalfStart;
        boolean result = true;
        while (result && p2 != null) {
            if (p1.val != p2.val) {
                result = false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }        

        // 还原链表并返回结果
        firstHalfEnd.next = reverseList(secondHalfStart);
        return result;
    }

    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;
    }

    private ListNode endOfFirstHalf(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
}

 

posted @ 2023-03-03 12:35  忧愁的chafry  阅读(13)  评论(0编辑  收藏  举报