【鏈表問題】打卡6:三種方法帶你優雅判斷迴文鏈表

前言

以專題的形式更新刷題貼,歡迎跟我一塊兒學習刷題,相信我,你的堅持,絕對會有意想不到的收穫。每道題會提供簡單的解答,若是你有更優雅的作法,歡迎提供指點,謝謝。ide

注:若是你在看代碼的時候發現代碼排版亂了麻煩告訴我一聲,謝謝。學習

【題目描述】

給定一個鏈表的頭節點 head, 請判斷該鏈表是否爲迴文結構。3d

例如:指針

1->2->1,返回 true.code

1->2->2->1, 返回 true。blog

1->2->3,返回 false。it

【要求】

若是鏈表的長度爲 N, 時間複雜度達到 O(N)。ast

【難度】

普通解法:士:★☆☆☆class

進階解法:尉:★★☆☆進階

【解答】

方法1

咱們能夠利用棧來作輔助,把鏈表的節點所有入棧,在一個一個出棧與鏈表進行對比,例如對於鏈表 1->2->3->2->2,入棧後如圖:

【鏈表問題】打卡6:三種方法帶你優雅判斷迴文鏈表
而後再逐一出棧與鏈表元素對比。

這種解法比較簡單,時間複雜度爲 O(n), 空間複雜度爲 O(n)。

代碼以下

1//方法1
 2public static boolean f1(Node head) {
 3    if (head == null || head.next == null) {
 4        return true;
 5    }
 6    Node temp = head;
 7    Stack<Node> stack = new Stack<>();
 8    while (temp != null) {
 9        stack.push(temp);
10        temp = temp.next;
11    }
12    while (!stack.isEmpty()) {
13        Node t = stack.pop();
14        if (t.value != head.value) {
15            return false;
16        }
17        head = head.next;
18    }
19    return true;
20}

方法二

真的須要所有入棧嗎?其實咱們也能夠讓鏈表的後半部分入棧就能夠了,而後把棧中的元素與鏈表的前半部分對比,例如 1->2->3->2->2 後半部分入棧後如圖:

【鏈表問題】打卡6:三種方法帶你優雅判斷迴文鏈表
而後逐個出棧,與鏈表的前半部分(1->2)對比。這樣作的話空間複雜度會減小一半。

代碼以下:

1//方法2
 2public static boolean f(Node head) {
 3    if(head == null || head.next == null)
 4        return true;
 5    Node slow = head;//慢指針
 6    Node fast = head;//快指針
 7    Stack<Node> stack = new Stack<>();
 8    //slow最終指向中間節點
 9    while (fast.next != null && fast.next.next != null) {
10        slow = slow.next;
11        fast = fast.next.next;
12    }
13    System.out.println(slow.value);
14    slow = slow.next;
15    while (slow != null) {
16        stack.push(slow);
17        slow = slow.next;
18    }
19    //進行判斷
20    while (!stack.isEmpty()) {
21        Node temp = stack.pop();
22        if (head.value != temp.value) {
23            return false;
24        }
25        head = head.next;
26    }
27    return true;
28}

方法三:空間複雜度爲 O(1)。

上道題咱們有做過鏈表的反轉的,沒看過的能夠看一下勒:【鏈表問題】如何優雅着反轉單鏈表],咱們能夠把鏈表的後半部分進行反轉,而後再用後半部分與前半部分進行比較就能夠了。這種作法額外空間複雜度只須要 O(1), 時間複雜度爲 O(n)。

代碼以下:

1//方法3
 2public static boolean f2(Node head) {
 3    if(head == null || head.next == null)
 4        return true;
 5    Node slow = head;//慢指針
 6    Node fast = head;//快指針
 7    //slow最終指向中間節點
 8    while (fast.next != null && fast.next.next != null) {
 9        slow = slow.next;
10        fast = fast.next.next;
11    }
12    Node revHead = reverse(slow.next);//反轉後半部分
13    //進行比較
14    while (revHead != null) {
15        System.out.println(revHead.value);
16        if (revHead.value != head.value) {
17            return false;
18        }
19        head = head.next;
20        revHead = revHead.next;
21    }
22    return true;
23}
24//反轉鏈表
25private static Node reverse(Node head) {
26    if (head == null || head.next == null) {
27        return head;
28    }
29    Node newHead = reverse(head.next);
30    head.next.next = head;
31    head.next = null;
32    return newHead;
33}

問題拓展

思考:若是給你的是一個環形鏈表,而且指定了頭節點,那麼該如何判斷是否爲迴文鏈表呢?

【題目描述】

【要求】

【難度】

未知。

【解答】

無。此題爲開放題,你能夠根據這個設定各類其餘要求條件。

  • End -

    往期

【鏈表問題】環形單鏈表約瑟夫問題

【鏈表問題】如何優雅着反轉單鏈表

【鏈表問題】刪除單鏈表的中間節點

【鏈表問題】刪除單鏈表中的第K個節點

【鏈表問題】打卡6:三種方法帶你優雅判斷迴文鏈表

相關文章
相關標籤/搜索