leetcode234---Palindrome Linked List(回文链表)

问题描述:

Given a singly linked list, determine if it is a palindrome.

Follow up:
Could you do it in O(n) time and O(1) space?

判断链表是否为回文链表。并且算法时间复杂度为O(n),空间复杂度为O(1)。

问题求解:

利用反转链表法,将链表后半段原地翻转,再将前半段和后半段进行比较,判断是否相等。
时间复杂度O(n),空间复杂度为O(1)

首先介绍快慢指针法。
(1)偶数个元素

        1 -> 2 -> 3 -> 3 -> 2 -> 1
慢指针:  s    s    s    s 
快指针:  f         f         f          f=NULL

因此,从slow处开始反转,即3 -> 2 -> 1 => 1 -> 2 -> 3

(2)奇数个元素

        1 -> 2 -> 3 -> 2 -> 1
慢指针:  s    s    s     
快指针:  f         f         f != NULL          

因此,从slow->next处开始反转,即2 -> 1 => 1 -> 2,并且更新后半段起点:slow = slow->next;

完整代码如下:

/** * 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) {
        if(!head || !head->next) return true;
        //(1)利用快慢指针法,寻找链表中心
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        if(fast)
        {//(2)链表有奇数个元素
            slow->next = reverseList(slow->next);
            slow = slow->next;//更新后半段的起点标志
        }
        else
        {//(3)链表有偶数个元素
            slow = reverseList(slow);
        }
        while(slow)
        {//(4)前后两段开始比较
            if(head->val != slow->val) return false;
            slow = slow->next;//推进后半段
            head = head->next;//推进前半段
        }
        return true;
    }
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = NULL;//翻转后,第一个节点的next为空
        ListNode* cur = head;
        while(cur != NULL)
        {
            ListNode* next = cur->next;//保存cur->next
            cur->next = pre;//改变相邻两节点指向
            //更新
            pre = cur;//将当前节点设置为pre
            cur = next;//推进当前节点
        }
        return pre;
    }
};

扩展:

也可以有另外的两种思路解决该问题,不过空间复杂度不符合。
1、遍历整个链表,将链表每个节点的值记录在数组中,再判断数组是不是一个回文数组,时间复杂度为O(n),空间复杂度O(n)。
2、利用栈先进后出的性质,将链表前半段压入栈中,再逐个弹出与链表后半段比较。时间复杂度O(n),仍需要n/2的栈空间,空间复杂度为O(n)。

你可能感兴趣的:(链表)