LeetCode热题100——234.回文链表(两种解法)

题目

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

示例 1:

输入: head = 1,2,2,1
**输出:**true

示例 2:

输入: head = 1,2
**输出:**false

法一(数组辅助+双指针):

题解

将链表中的数值复制到一个数组中,然后使用双指针从两端向中间比较即可

答案

cpp 复制代码
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> nums;
        while(head!=NULL){
            nums.push_back(head->val);
            head=head->next;
        }
        int i=0,j=nums.size()-1;
        while(i<j){
            if(nums[i]==nums[j]){
                i++;
                j--;
            }
            else {
                return false;
            }
        }
        return true;
    }
};

复杂度分析

  • 时间复杂度 :O(n)

    遍历链表一次 O(n),双指针遍历数组一次 O(n/2) ≈ O(n)。

  • 空间复杂度 :O(n)

    使用一个与链表长度相同的数组存储所有节点的值。

法二(快慢指针找中点+反转后半段链表):

题解

1.使用快慢指针找到链表的中间节点(前半部分的尾节点)。

  • 定义快指针 fast 和慢指针 slow,都指向 head。
  • 当 fast->next 和 fast->next->next 均不为空时,fast 每次移动两步,slow 每次移动一步。
  • 循环结束时,slow 指向的就是前半部分的尾节点。

2.反转链表的后半部分(详见如下解析:题目LeetCode热题100------206.反转链表)

https://blog.csdn.net/wyhwyh___/article/details/160566554?spm=1001.2014.3001.5501https://blog.csdn.net/wyhwyh___/article/details/160566554?spm=1001.2014.3001.5501

3.同时遍历前半部分和反转后的后半部分,比较对应节点的值是否相等。

4.恢复链表原状。

答案

cpp 复制代码
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode* firstHalfEnd = endOfFirstHalf(head);
        ListNode* secondHalfStart = reverseList(firstHalfEnd->next);

        ListNode* p1=head;
        ListNode* p2=secondHalfStart;
        while(p2!=NULL){
            if(p1->val!=p2->val) return false;
            p1=p1->next;
            p2=p2->next;
        }
        //恢复链表
        firstHalfEnd->next=reverseList(secondHalfStart);
        return true;
    }

    //快慢指针找前半部分的尾节点
    ListNode* endOfFirstHalf(ListNode* head){
        ListNode* fast=head;
        ListNode* slow=head;
        while(fast->next!=NULL&&fast->next->next!=NULL){
            fast=fast->next->next;
            slow=slow->next;
        }
        return slow;
    }

    //反转链表,返回后半部分的新头节点
    ListNode*reverseList(ListNode* head){
        ListNode* pre=NULL;
        ListNode* cur=head;
        while(cur!=NULL){
            ListNode* nextTemp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=nextTemp;
        }
        return pre;
    }
    
};

复杂度分析

  • 时间复杂度 :O(n)

    找中点 O(n),反转链表 O(n),比较 O(n),整体 O(n)。

  • 空间复杂度 :O(1)

    只使用了若干个指针变量,没有使用额外的数组或递归栈。

相关推荐
benben04411 分钟前
强化学习之DQN算法族(基于gymnasium开发)
算法
玖玥拾1 小时前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
何以解忧,唯有..1 小时前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
想吃火锅10052 小时前
【leetcode】88.合并两个有序数组js
算法
один but you2 小时前
constexpr函数
c++
生成论实验室3 小时前
机器人:一个自主运动的系统
人工智能·算法·语言模型·机器人·自动驾驶·agi·安全架构
Qres8213 小时前
算法复键——树状数组
数据结构·算法
H178535090963 小时前
SolidWorks第四部分_直接实体建模特征9_替换面原理
线性代数·算法·机器学习·3d建模·solidworks
凡人叶枫3 小时前
Effective C++ 条款41:了解隐式接口和编译期多态
java·开发语言·c++·effective c++