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)

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

相关推荐
IronMurphy1 小时前
【算法四十二】118. 杨辉三角 198. 打家劫舍
算法
电科一班林耿超1 小时前
第 16 课:动态规划专题(二)—— 子序列与子数组问题:面试最高频的 DP 题型
数据结构·算法·动态规划
愚者游世1 小时前
noexcept 说明符与 noexcept运算符各版本异同
开发语言·c++·程序人生·面试·visual studio
生信研究猿2 小时前
leetcode 416. 分割等和子集
算法·leetcode·职场和发展
狗哥哥2 小时前
面包屑自动推导的算法设计:从“最短路径匹配”到工程可落地
算法·架构
极客BIM工作室2 小时前
OCCT开发实践:空间封闭曲线生成曲面的思考与总结
c++
澈2072 小时前
C++多态编程:从原理到实战
开发语言·c++
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 24. 两两交换链表中的节点 | C++ 精准指针舞步
c++·leetcode·链表