LeetCode链表234. 回文链表

题目描述

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

示例 1:

输入: 1->2
输出: false

示例 2:

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

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

题解

思路一:数组

使用数组存储链表中的元素,用两个指针从首尾遍历判断

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == NULL) return true;
        ListNode* temp = head;
        //设置一个哨兵,存储最终结果
        bool flag = 1;
        int n = 0,i = 0;
        //获取链表长度
        while(temp != NULL){
            temp = temp->next;
            n++;
        }
        temp = head;
        int* p = new int[n];
        //将链表中节点的值放入数组
        while(temp != NULL){
            p[i++] = temp->val;
            temp = temp->next;
        }
        n = 0;
        //判断是否为回文链表
        //当头部指针 < 尾部指针时,所有判断完成
        while(i >= n){
            if(p[n++] != p[--i] ) flag = 0;
        }
        delete[] p;
        return flag;

    }
};

思路二:递归

递归结束条件:head->next ==NULL
使用两个指针*p,*q 判断前后两个回文位置是否相等
p指向头部
q指向当前遍历的节点
q节点每次往前移动一次,p = p->next
p从前往后遍历全部节点,q从后往前遍历全部节点
只要发现一次p->val != q->val 接下来一直返回false
若是回文节点 一直返回true

在这里插入图片描述

class Solution {
public:
    //默认为回文链表,返回值为true
    bool flag = 1; 
    //哨兵:判断是否为头结点
    int f1=0;
    //头部指针
    ListNode *p = NULL;
    bool isPalindrome(ListNode* head) {
    //判断是否为头节点,让p指向头结点
        if( f1 == 0){
            f1++;
            p = head;
        }
        // 递归终止条件 or 判断是否为空
        if(head == NULL) return true;
        //让q指向当前遍历节点,q会从尾部开始使用
        ListNode* q=head;
        //递归开始
        flag = isPalindrome(head->next);
        //已经判断过的节点全为回文节点对,则继续判断
        if(flag) {
        //非回文节点
           if(p->val != q->val) {
               p = p->next;
               return false;
            }
            //回文节点
           else if(p->val == q->val){
               p = p->next;
               return true;
            }
        }
        //一旦出现非回文节点,不再判断,直接返回false
        else if (!flag )return flag;
    return flag;
    }
};

思路三:栈

用栈顺序存储链表中的节点,利用栈先进后出的特性判断每对回文节点

class Solution {
public:
    bool isPalindrome(ListNode* head) {
       stack<int> s;
       ListNode* p = head;
       while(p){
           s.push(p->val);
           p = p->next;
       }
       while(head){
           if(head->val != s.top())
              return 0;
            s.pop();
            head = head->next;
       }
       return 1;
    }
};

思路四:反转链表

一、快慢指针:翻转后半部分

使用快慢指针,快指针一次走两个节点,慢指针一次走一个,当快指针走到尾部,慢指针走到了中间。

翻转后半部分的链表,翻转链表题目已经写过,详情点击链接:
Leetcode链表206. 反转链表
然后依次比较即可
若是奇数个节点,前后两个链表全都指向中间节点
若为偶数个节点,前后链表最后两个节点是对称的

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if(head == NULL || head->next == NULL)
           return true;
        ListNode* q = head;
        ListNode* s = head;
        while(q && q->next){
            q = q->next->next;
            s = s->next;
        }
        s = reverseList(s);
        while(s){
            if(head->val != s->val)
               return false;
            s = s->next;
            head = head->next;
        }
        return true;
    }
    ListNode* reverseList(ListNode* head) {
        ListNode* pre  = NULL;
        ListNode* cur = head;
        while (cur != NULL){
            ListNode* temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

二、快慢指针:翻转前半部分

慢指针边走边翻转
思路差不多,就是把翻转代码直接放到第一次while循环里面,不想写了,就直接从LeetCode上面扣下来的

class Solution {
public:
    bool isPalindrome(ListNode* head) {
    //无节点
        if(!head)
            return true;
    //一个节点
        if(!head->next)
            return true;
        bool res = 1;
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode* reverse = head;
        ListNode* reverse_pre = NULL;
        ListNode* start;
        while(fast->next && fast->next->next){
            fast = fast->next->next;
            reverse = slow;
            slow = slow->next;
            reverse->next = reverse_pre;
            reverse_pre = reverse;
        }
        //判断是否为节点数>2的偶数个节点,将最后一个节点接在头部
        if(fast->next &&fast!=head){
            start = slow->next;
            slow->next = reverse;
            reverse = slow;}
        //奇数个节点或者只有两个节点的情况
        else
            start = slow->next;
       
        while(start && reverse){
            if(start->val != reverse->val)
                res = 0;
            start = start->next;
            reverse = reverse->next;
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值