[leetcode] PalindromeLinkedList

本文探讨了两种高效判断单向链表是否为回文结构的方法。第一种方法使用递归,通过比较链表首尾元素实现。第二种方法则在O(1)空间复杂度下,将链表一分为二并反转后半部分,再进行对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PalindromeLinkedList

  • 问题描述:给定一个单向链表,试判断该链表是否是回文链表。
  • 解决思路1
    • 因为该链表是单向的,所以我们不能想vector那样从后向前访问。
    • 所以我们可以先将ListNode存储起来,然后再判断
    • 或者是说我们可以利用递归的方法来判断。
      • 我们首先用tmp保存head元素。
      • 然后利用递归遍历head,访问每一个元素。
      • 访问最后一个时候比较该元素和tmp
        • 如果相等,则tmp = tmp->next,return true,返回上一个节点
        • 如果不想等,则直接return false
  • 解决思路2
    • 如果要求我们只能利用O(1)的存储空间呢?上面的思路都用了O(N)的存储空间
    • 其实试想因为我们要判断它是不是回文。所以如果说我们能把list一分为2,并且后半段reverse一下,是不是就可以了?
    • 所以我们先考虑将list一分为2。
      • 我们利用两个指针,一快一慢,快的走两部,慢的走一步。当快的走到最后一个时候,慢的刚好走在一半处。
      • 这里有点需要注意。如果快的只走了一步就到了最后一个节点,那么慢的不走。
      • 代码如下所示
      		ListNode* dump = new ListNode(0);
              dump->next = head;
              ListNode* slow = dump;
              ListNode* fast = dump;
              while(slow->next && fast->next){
                  fast = fast->next;
                  if(fast->next){
                      fast = fast->next;
                      slow = slow->next;
                  }
              }
      
      • 接下来我们考虑reverse后半段。
        • 因为我们slow其实代表的就是前半段的最后一个节点。所有我们slow->next 就是后半段的第一个元素。
      • reverse完成之后,我们再逐个对比即可。
      • 整体下来时间复杂度是O(n),空间复杂度是O(1)
  • 代码
//
// Created by 梁栋 on 2019-05-16.
//
#include <iostream>
#include <vector>
using namespace std;
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
    static ListNode* ListNodeFromVector(vector<int> xs){
        ListNode* head = new ListNode(0);
        ListNode* first = head;
        for(int i=0;i<xs.size();i++){
            head->next = new ListNode(xs[i]);
            head = head->next;
        }
        return first->next;
    }
    void print(){
        ListNode* head = this;
        while(head){
            cout<<head->val<<"->";
            head = head->next;
        }
        cout<<endl;
    }
};
class Solution {
public:
    ListNode* tmp;
    bool isPalindrome(ListNode* head) {
        // 判断list是否是回文list
        tmp = head;
        return check(head);
    }
    bool check(ListNode* head){
        if(head == NULL)
            return true;
        if(check(head->next) && head->val == tmp->val){
            tmp = tmp->next;
            return true;
        }
        return false;
    }
    bool isPalindromeV2(ListNode* head){
        if(head == NULL)
            return true;
        ListNode* dump = new ListNode(0);
        dump->next = head;
        ListNode* slow = dump;
        ListNode* fast = dump;
        while(slow->next && fast->next){
            fast = fast->next;
            if(fast->next){
                fast = fast->next;
                slow = slow->next;
            }
        }
        ListNode* last2 = NULL;
        ListNode* start2 = slow->next;
        while(last2 != fast){
            ListNode* tmp = start2->next;
            start2->next = last2;
            last2 = start2;
            start2 = tmp;
        }
        slow->next = NULL;
        slow = head;
        while(slow && fast){
            if(slow->val == fast->val)
            {
                slow = slow->next;
                fast = fast->next;
                continue;
            }else{
                return false;
            }
        }
        return true;
    }
    static void solution(){
        ListNode* head = ListNode::ListNodeFromVector({});
        Solution solution1;
        cout<<solution1.isPalindromeV2(head)<<endl;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值