LeetCode_234. 回文链表

题目:

请判断一个链表是否为回文链表。

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法一:

将链表依次拷贝到一个vector数组中,然后使用前后双指针判断vector是否符合回文要求。

时间复杂度: O(n)
空间复杂度: O(n)

需要注意的两点:
(1)[ ] 空链表也属于回文链表,所以在函数入口不能加head==null的特例判断;
(2)for循环的终止条件是(start<end),不能写成(start!=end),否则会死循环且数组越界访问。

/**
 * 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 == nullptr || head->next == nullptr) return false;
        vector<int> v;
        while(head != nullptr) {
            v.push_back(head->val);
            head = head->next;
        }
        for(int start = 0, end = v.size()-1; start < end; ++start, --end) {
            if(v[start] != v[end]) return false;
        }
        return true;
    }
};

解法二:翻转后半部分链表:

时间复杂度: O(n)
空间复杂度: O(1)

注意以下几点:
(1)在对后半部分链表翻转并比较后,要再将其二次翻转恢复链表状态,因此函数的调用者是不希望改变链表本身的;
(2)compare()步骤不能要求在first与second两个指针比较都都变成空,这种情况只有在链表结点数为偶数个时才可能成立,对于奇数个结点的链表,中间的一个结点的值可以为任意值,都满足回文字符串的要求。

思考: 写这道题时使用了“自顶向下”的编程方法,主函数中只写操作流程:split(分前后两段)、reverse(翻转后半段)、compare(比较)、reverse(恢复),细分的功能则放在后面逐个实现。
这样的好处时不会因为一直在细节中纠缠而导致思路不清,最后写出来的代码也是错误百出,难于调试。

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(head == nullptr) return true; //别扭的特例判断,不得不加
        ListNode* tail = split(head);
        ListNode* halfHead = reverse(tail->next);
        tail->next = nullptr; //断链
        bool result = compare(head, halfHead);
        tail->next = reverse(halfHead); //恢复,二次翻转
        return result;
    }
    ListNode* split(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast->next != nullptr && fast->next->next != nullptr) {
            slow = slow->next;
            fast = fast->next->next; 
        }
        return slow; //tail
    }
    ListNode* reverse(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* res = reverse(head->next);
        head->next->next = head;
        head->next = nullptr;
        return res;
    }
    bool compare(ListNode* first, ListNode* second) {
        while(first != nullptr && second != nullptr) {
            if(first->val != second->val) return false;
            first = first->next;
            second = second->next;
        }
        return true; 
        //(first == nullptr && second == nullptr);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值