码迷,mamicode.com
首页 > 其他好文 > 详细

如何判断一个单向链表是否为回文链表(Palindrome Linked List)

时间:2015-10-14 21:46:32      阅读:845      评论:0      收藏:0      [点我收藏+]

标签:

题目:给定一个单向链表,判断它是不是回文链表(即从前往后读和从后往前读是一样的)。原题见下图,还要求了O(n)的时间复杂度O(1)的空间复杂度。技术分享

我的思考:

1,一看到这个题目,大脑马上想到的解决方案就是数组。遍历链表,用数组把数据存下来,然后再进行一次遍历,同时用数组反向地与之比较,这样就可以判断是否回文。这个方法时间复杂度是O(n),达到了要求,然而空间复杂度显然不满足要求。所以,开数组这一类的方法显然不是最佳的。

2,既然要满足O(1)的空间复杂度,我就想到了用一个变量来存储这些数据,恰好题目给出的数据也是整型。具体思路就是用一个long int:sum来存储这些数据,第一次遍历:第一个节点的数据乘1加到sum,第二个节点的数据乘10加到sum……;然后再反向遍历一次,sum减去最后一个节点的数据乘1,sum减去倒数第二个节点的数据乘10……。只要看最后的sum是否为0就可以判断链表是否回文。当然,在第一次遍历的时候需要一边遍历一边逆置该链表,才能进行第二次遍历。贴上代码:

/**
 * 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 *point1, *point2, *point3;
        point3 = point2 = head;
        point1 = NULL;
        long int sum = 0;
        int n = 1;
        if(head == NULL || head->next == NULL)
            return true;
        while(point3->next != NULL)//第一次遍历,取值并逆置
        {
            sum += n*point3->val;
            n *= 10;
            point3 = point3->next;
            point2->next = point1;
            point1 = point2;
            point2 = point3;
        }
        sum += n*point3->val;
        point2->next = point1;
        n = 1;
        while(point2 != NULL)//第二次遍历
        {
            sum -= n*point2->val;
            n *= 10;
            point2 = point2->next;
        }
        if(sum == 0)
            return true;
        else
            return false;
    }
};

刚开始觉得这个方法应该没问题,然而在LeetCode上提交之后:技术分享

遇到这个案例中这堆变态的数据时,这个方法就不行了,sum肯定会溢出。可以看到21个test还是可以通过20个的,说明这个方法可以用于一般情况。

3,不能用一个数来存储信息,那只能直接比较节点里的信息了。怎么比较?我们知道回文链表的特点就是对称,那么要判断是否回文就可以用两个指针指向对称的节点,看里面的数是否相等。即对称的位置是否有对称的数值。由于是单向链表,不能同时用两个指针从头尾向内部遍历取值比较。那么就考虑从链表中间开始,用两个指针向两头遍历取值比较,显然这也需要进行链表逆置。

具体的做法就是先遍历一次链表得到链表长度。然后第二次遍历到链表中间,并在遍历的时候进行逆置。然后两个指针分离,分别向两个端点移动,同时进行比较,数值相同则继续,数值不同则直接返回false。直到遍历完成,最后返回true。代码:

/**
 * 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) 
    {
        int lenth, i;
        ListNode *point1, *point2, *point3;
        point3 = point2 = head;
        point1 = NULL;
        lenth = 0;
        if(head == NULL || head->next == NULL)
            return true;
        while(point3 != NULL)//取得长度
        {
            point3 = point3->next;
            lenth++;
        }
        for(i = 0;i < (lenth / 2);i++)//遍历到中间,并逆置
        {
            point3 = point2->next;
            point2->next = point1;
            point1 = point2;
            point2 = point3;
        }
        if((lenth % 2) == 1)
            point3 = point3->next;
        while(point3 != NULL && point1 != NULL)//两个指针开始向两头移动,取值比较
        {
            if(point3->val != point1->val)
                return false;
            point3 = point3->next;
            point1 = point1->next;
        }
        return true;//比较中没有发现不同值,则为回文链表
    }
};

最后的结果也证明这个方法是可行的:

技术分享

 

若博文中有什么不正确的地方欢迎大家指正,谢谢~

如何判断一个单向链表是否为回文链表(Palindrome Linked List)

标签:

原文地址:http://www.cnblogs.com/HorribleMe/p/4878833.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!