暫時接觸到LeetCode上與鏈表反轉相關的題目一共有3道,在這篇博文里面總結一下。首先要講一下我一開始思考的誤區:鏈表的反轉,不是改變節點的位置,而是改變每一個節點next指針的指向。
下面直接看看LeetCode上的題目:
206. Reverse Linked List
這是一道最基本的鏈表反轉題目。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { if (head == NULL || head->next == NULL) return head; ListNode *p = head; ListNode *q = head->next; head->next = NULL; while (q) { ListNode *r = q->next; q->next = p; p = q; q = r; } return p; } };
其實就是不斷地將當前訪問到的位置的next指針指向它前面的指針,這是最基本的操作了。
92. Reverse Linked List II
這道題目規定了要進行反轉的位置區間,比上一題加大了難度。我們要先添加一個頭指針,指向head節點(最后返回頭指針的next即可);然后一直往后訪問,一直到要反轉的節點的前一位停下來。
我們要記錄下兩個節點的位置:開始反轉位置的節點的前一位、開始反轉位置的節點。因為在反轉后,開始反轉的節點的前一個節點的next指針要指向反轉的最后一個節點,開始反轉的節點的next要指向反轉的最后一個節點的后一個節點。
然后進行與上面一題同樣的反轉即可。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseBetween(ListNode* head, int m, int n) { if (m == n) return head; ListNode *cur = new ListNode(0); cur->next = head; ListNode *copy = cur; for (int i = 0; i < m - 1; i++) { cur = cur->next; } ListNode *temp1 = cur, *temp2 = cur->next; cur = cur->next; ListNode *p = cur, *q = cur->next; for (int i = m; i < n; i++) { ListNode *r = q->next; q->next = p; p = q; q = r; } temp1->next = p; temp2->next = q; return copy->next; } };
234. Palindrome Linked List
這一題要求在O(n)的時間復雜度和O(1)的空間復雜度下,判斷一個鏈表是否回文鏈表。
我們可以利用一快一慢兩個指針同時前進,當快指針到鏈表的末尾(即不能往后走)時,慢指針就走到序列中間。(這里有一點值得注意,就是無論節點個數是奇數還是偶數,此時從慢指針指向的節點的后一個節點開始反轉就可以了)。反轉后,對鏈表的前半部分和后半部分逐個比較即可。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool isPalindrome(ListNode* head) { ListNode *copy = head; if (head == NULL || head->next == NULL) return true; ListNode * slow = head, *fast = head; while (fast->next && fast->next->next) { slow = slow->next; fast = fast->next->next; } slow = slow->next; ListNode *p = slow; ListNode *q = slow->next; slow->next = NULL; while (q) { ListNode *r = q->next; q->next = p; p = q; q = r; } while (p) { if (p->val != copy->val) { return false; } p = p->next; copy = copy->next; } return true; } };