题目没有说明可以更改输入链表,其实有点擦边了。

就谈这个算法,我之前为了定位到中间那个节点,一直是用计数操作。

期间为了精确确定i =0 , i<n/2 这个边界,纠结模拟半天。好费劲啊!这一点太弱了。

bool judge(struct ListNode *p,struct ListNode *q)
{
    while( p && q)
    {
        if(p->val != q->val)    return false;
        p = p->next;
        q = q->next;
    }
    return p==NULL && q==NULL;
}

bool isPalindrome_using_count(struct ListNode* head) {
    int i,n = 0;
    struct ListNode * p = head, *last = NULL, *pre= NULL;
    
    while(p!=NULL)
    {
        n ++;
        p=p->next;
    }
    
    if(n < 2)   return true;
    
    p = head;

    for( i = 0; i < n/2; i++)
    {
        pre = p->next;
        p->next = last;
        
        last = p;
        p = pre;
    }
    if(n%2 != 0)    return judge(last,pre->next);
    else            return judge(last,p);
}

 

人家用了快慢指针的方法,定位到最后,slow就是指向最中间那个(奇数个) 或者中间偏左那个 (偶数个)。

然后就容易了。可以把后面翻转,然后和head一个一个比较,最后结果是两个指针均为空,或者head多出一个。

另一种方法是,把前面翻转,和后面比较。单数的话,需要在后面新增一个最中间的节点。

代码

bool isPalindrome(struct ListNode* head) {
    struct ListNode * fast, *slow;
    
    fast = slow = head;
    
    if(head == NULL || head->next == NULL)  return true;
    
    while(fast->next && fast->next->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    
    struct ListNode * p1, *p2;
    

    p2 = reverse(slow->next);
    
    slow->next = NULL;
    p1 = head;
    while(p1 && p2)
    {
        if(p1->val != p2->val)  return false;
        
        p1= p1->next;
        p2= p2->next;
    }
    
    return p1 == NULL || p1->next == NULL;

}

 

posted on 2017-11-29 12:29  newbird2017  阅读(115)  评论(0)    收藏  举报