LeetCode(c++)回文链表

题目如下:
请判断一个链表是否为回文链表。

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

进阶:

你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

思路一:

首先读题,不考虑进阶情况的话,由于回文链表的数值是对称的。

因此,我们可以遍历一遍输入的链表,声明两个空的vector 分别为left和right,每读取一个值,将节点的node->val在left的左边插入,在right的右边插入。

可以想得到,我们得到的right的顺序和链表的数值的顺序是一样的;而left的数值的顺序和链表的数值顺序相反。

由于回文链表的数值对称,因此,如果我们最终得到的两个vector是相等的话,则这个链表是回文链表。

这样做的只用了一次遍历,时间复杂度是O(n),但是用了两个长度为n的vector,因此空间复杂度为O(n)。

解答代码如下:

class Solution 
{
public:
    bool isPalindrome(ListNode* head) 
    {
        if (!head || !(head->next))
        {
            return true;
        }
        vector<int> left;
        vector<int> right;
        while (head)
        {
            left.insert(left.begin(), head->val);
            right.push_back(head->val);
            head = head->next;
        }
        return left == right;
    }
};

思路二:

我们之前用的方法时间复杂度达到了要求,但是空间复杂度不符合进阶的要求。

我之前做过反转链表的题目,于是想到,首先设置一个first节点,指向链表表头;
然后遍历一次得到链表长度count,然后从链表的(count + 1)/2的地方开始,反转链表(也就是说将链表的后半部分反转,奇数链表的话反转过后后半部分少一个节点,比如,五个节点的链表,前面三个节点,后面两个节点);反转之后得到原本链表尾巴上的节点,将头结点和尾节点同时开始遍历,即可判断出结果。

这一思路,一共用了三个ListNode指针,空间复杂度为O(1);一共遍历四次,时间复杂度为O(n),符合进阶要求。

代码如下:

/**
 * 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;
        }
        ListNode* first = new ListNode(0);
        first = head;
        int count = 1;

        while (head->next)
        {
            count += 1;
            head = head->next;
        }
        head = first;

        count = (count + 1) / 2;

        while (count > 0)
        {
            head = head->next;
            count--;
        }
        // head = first;
        ListNode* pre;
        ListNode* pnext;
        pre = NULL;
        // cout << head->val << endl;
        while (head->next)
        {
            pnext = head->next;
            head->next = pre;
            pre = head;
            head = pnext;
        }
        head->next = pre;


        while(head)
        {
            if(first->val != head->val)
            {
                // delete first;
                return false;
            }
            head = head->next;
            first = first->next;
        }
        // delete first;
        return true;
    }
};

这里遇到了一个问题,就是不注释delete的话会报错,报错信息为:double free or corruption (out)。

感觉要代码还是可以继续改得简洁一点,不过感觉这样代码挺好读懂的,希望各位大佬批评指正,提出一下更好的思路。

你可能感兴趣的:(leetcode)