數據結構複習到了鏈表,順便也把這個題解了
leet上最快的解題是把鏈表的內容複製到數組,然後從數組兩端比較
我的解法只使用了鏈表,所以會慢於數組解法
思路:
- 使用快慢指針來確定鏈表的中間位置,慢指針每次走一步,快指針走兩步
如果是ABCD偶數個元素情況,慢指針最後會指向B;快指針由於初始化時提前移動了一位(即初始化時慢指針指向A,快指針指向B),所以快指針最後指向D
如果是ABCDE奇數個情況,慢指針恰好指向中點C,快指針指向E - 將慢指針之後的鏈表斷開(或者視爲兩個鏈表),然後對後半鏈表進行逆反操作
- 對兩部分鏈表從頭開始比較,如果有不同則不是迴文鏈表。
- 對後半部分鏈表再次進行逆操作,恢復原順序,再將前半鏈表和後半鏈表鏈接起來,恢復初始狀態。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverse_list(struct ListNode *list)
{//abc -> cba
struct ListNode *tail = list;
struct ListNode *ptr = list;
struct ListNode *fast;
while(tail->next != NULL)
tail = tail->next;
while(ptr != tail)
{
fast = ptr->next;
ptr->next = tail->next;
tail->next = ptr;
ptr = fast;
}
return tail;
}
bool processing(struct ListNode *list,const int length)
{
if(list == NULL)
return false;
bool re = true;
struct ListNode *slow = list;
struct ListNode *fast = list;
if((length & 1) == 0)
fast = fast->next;//提前走一步 爲了找到tail
while (fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
struct ListNode *middle_left = slow;
slow = slow->next; //中後的第一個位置
struct ListNode *new_head = reverse_list(slow);
slow = new_head;
fast = list;
while (slow != NULL)
{
if (slow->val != fast->val)
{
re = false;
break;
}
slow = slow->next;
fast = fast->next;
}
//恢復list
new_head = reverse_list(new_head);
middle_left->next = new_head;
return re;
}
bool isPalindrome(struct ListNode* head) {
struct ListNode* ptr = head;
int length=0;
while(ptr!=NULL)
{
++length;
ptr = ptr->next;
}
if(length<=1)
return true;
return processing(head,length);
}