天天看點

精選力扣500題 第40題 LeetCode 234. 回文連結清單【c++/java詳細題解】

目錄

  • ​​1、題目​​
  • ​​2、思路​​
  • ​​3、c++代碼​​
  • ​​4、java代碼​​

1、題目

請判斷一個連結清單是否為回文連結清單。

示例 1:

輸入: 1->2
輸出: false      

示例 2:

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

進階:

你能否用 時間複雜度和 空間複雜度解決此題?

2、思路

(連結清單操作)

假設初始的連結清單是 。

精選力扣500題 第40題 LeetCode 234. 回文連結清單【c++/java詳細題解】

分兩步處理:

  • 找到連結清單的中點節點,将其後半段的指針都反向,變成:;
    精選力扣500題 第40題 LeetCode 234. 回文連結清單【c++/java詳細題解】
  • 然後用兩個指針分别從連結清單首尾開始往中間掃描,依次判斷對應節點的值是否相等,如果都相等,說明是回文連結清單,否則不是。
    精選力扣500題 第40題 LeetCode 234. 回文連結清單【c++/java詳細題解】
  • 最後再将整個連結清單複原。

注意點:

  • 1、我們選取連結清單的中點節點為 下取整,是連結清單的節點個數。
  • 2、如果一個連結清單是奇數個節點(假設為5個節點),将其後半段翻轉完後的連結清單為:
精選力扣500題 第40題 LeetCode 234. 回文連結清單【c++/java詳細題解】
  • 3、如果一個連結清單是偶數個節點(假設為4個節點),将其後半段翻轉完後的連結清單為:
精選力扣500題 第40題 LeetCode 234. 回文連結清單【c++/java詳細題解】
  • 4、上圖說明連接配接左右連結清單節點之間的指向是雙向的,具體實作細節看代碼

空間複雜度分析: 連結清單的疊代翻轉算法僅使用額外 的空間,是以本題也僅使用額外 的空間。

3、c++代碼

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        int n = 0 ; //統計節點的個數
        for(ListNode *p = head ; p ; p = p->next) n++;
        if(n <= 1) return true; //節點數<=1的一定是回文連結清單
        //找到中點節點,由第一個節點跳(n+1)/2 -1步到達中點節點
        ListNode* a = head;
        for(int i = 0; i < (n+1)/2 - 1; i++) a = a->next; //a指針指向連結清單中點
        ListNode* b = a->next;  //b指針指向連結清單中點的下一個節點
        while(b) //将連結清單的後半段反向
        {
            ListNode* next = b->next; //保留b的next節點
            b->next = a;
            a = b, b = next;
        }
        //此時a指向連結清單的尾節點,我們讓b指向連結清單的頭節點
        b = head;
        ListNode* tail = a; //保留一下尾節點
        bool res = true;
        for(int i = 0; i < n/2; i++) //判斷是否是回文連結清單
        {
            if(b->val  != a->val)
            {
                res = false;
                break;
            }
            b = b->next;
            a = a->next;
        }
        //将連結清單複原,後半段連結清單翻轉
        //a指向尾節點,b指向a的下一個節點
        a = tail, b = a->next;
        for(int i = 0; i < n/2; i++)
        {
            ListNode* next = b->next;
            b->next = a;
            a = b , b = next;
        }
        tail->next = 0;
        return res;
    }
};      

4、java代碼

/**
 * 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) {
        int n = 0 ; //統計節點的個數
        for(ListNode p = head ; p!=null ; p = p.next) n++;
        if(n <= 1) return true; //節點數<=1的一定是回文連結清單
        //找到中點節點,由第一個節點跳(n+1)/2 -1步到達中點節點
        ListNode a = head;
        for(int i = 0; i < (n+1)/2 - 1; i++) a = a.next; //a指針指向連結清單中點
        ListNode b = a.next;  //b指針指向連結清單中點的下一個節點
        while(b!=null) //将連結清單的後半段反向
        {
            ListNode next = b.next; //保留b的next節點
            b.next = a;
            a = b;
            b = next;
        }
        //此時a指向連結清單的尾節點,我們讓b指向連結清單的頭節點
        b = head;
        ListNode tail = a; //保留一下尾節點
        boolean res = true;
        for(int i = 0; i < n/2; i++) //判斷是否是回文連結清單
        {
            if(b.val  != a.val)
            {
                res = false;
                break;
            }
            b = b.next;
            a = a.next;
        }
        //将連結清單複原,後半段連結清單翻轉
        //a指向尾節點,b指向a的下一個節點
        a = tail;
        b = a.next;
        for(int i = 0; i < n/2; i++)
        {
            ListNode next = b.next;
            b.next = a;
            a = b ;
            b = next;
        }
        tail.next = null;
        return res;
    }
}