每日一题——回文链表

173 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

给定一个链表的 头节点 head 请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

示例 1:

image-20220317073143035

输入: head = [1,2,3,3,2,1] 输出: true

示例 2:

image-20220317073212035

输入: head = [1,2] 输出: false

提示:

链表 L 的长度范围为 [1, 105] 0 <= node.val <= 9

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

思路

该题是一道简单题,比较考察人的思维能力。我们可以很容易想到多种解决方案,可以先遍历链表,把链表中所有的值都存入一个数组中,然后利用栈的数据结构进行优化,先把一半的元素入栈,然后挨个出栈与数组中后面的元素进行比较,不相同则返回fasle,如果栈为空,说明这个数组是回文数组即返回true。

这样做的空间复杂度很高,我们可以利用双指针算法进行优化,用一个指针指向数组的开头,另一个指针指向数组的结尾,两个指针互相靠近直到相遇,如果出现两指针值不同,则返回false。这样利用指针替代了栈,可以降低空间复杂度。

代码

使用栈

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode* p = head;
        vector<int> ans;
        stack<int> s1;
        int j = 0;
        while(p != nullptr)
        {
            ans.push_back(p -> val);
            p = p -> next;
            j ++;
        }
        //for(int i = 0;i < j;i ++) cout << ans[i];
        int length = ans.size();
        
        
        int aa = 0;
        if(length % 2 == 0) aa = length / 2;
        else aa = length / 2 + 1;
        
        for(int i = 0;i < length / 2; i++)
        {
                s1.push(ans[i]);
        }
        while(!s1.empty() && aa < length)
        {
            if(s1.top() != ans[aa ++]) break;
            s1.pop();
        }
        return s1.empty();
    }
};

使用双指针

​
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode* p = head;
        vector<int> ans;
        stack<int> s1;
        int j = 0;
        while(p != nullptr)
        {
            ans.push_back(p -> val);
            p = p -> next;
            j ++;
        }
        //for(int i = 0;i < j;i ++) cout << ans[i];
        int length = ans.size();
​
        //  双指针
        for(int i = 0 ,j = length - 1;i < j;i ++ ,j --)
        {
            if(ans[i] != ans[j]) return false;
        }
        return true;
       
    }
};

总结

遇到判断回文串时,可以使用双指针算法求解。