力扣Hot100——234.回文链表

234.回文链表

解题思路

回文链表的话,就是第一个数和倒数第一个数相同,第二个数和倒数第二个数相同,一次类推,但是链表我们无法直接从最后一个节点开始从后往前推,因此对于判断是不是回文链表,首先我们需要找到链表的中间节点

1. 链表的中间节点

对于长度为奇数 的链表,正中间的节点就是中间节点。

对于长度为偶数 的链表,找正中间右边的节点。

举例如下:

对于链表

1->2->3->4->5

中间节点就是正中间的3。

对于链表

1->2->3->4->5->6

中间节点是正中间右边的4。

2.反转链表

随后对得到了中间节点之后的链表部分进行反转链表,也就是说:

奇数链表:

3->4->5反转为3<-4<-5,而另一边1->2->3

偶数链表

1->2->3->4,而另一边4<-5<-6。

3.回文链表判断

我们记反转后的头节点是head2。

同时得注意得到了反转之后的链表之后,进行回文判断的时候,判断条件当中应该是head2是否为空,如果判断条件当中是head的话,那么对于奇数情况,head要比head2多走一步,但这时候head2已经是空的了,就会出现问题(head2.val,空指针异常)。

如何得到链表的中间节点呢?

使用快慢指针法,让快慢指针同时指向head,快指针每次移动2步,慢指针每次移动1步,当快指针为null或者快指针的next为null时,此时满指针的所指就是中间节点。

代码

C++

cpp 复制代码
/**
 * 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:
    //找到中间节点
    ListNode* Getmidddle(ListNode* head)
    {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        } 
        return slow;
    }

    //反转中间节点之后的链表部分
    ListNode* ReverseLink(ListNode* head)
    {
        ListNode* pre = NULL;
        ListNode* cur = head;
        ListNode* nxt = NULL;
        while(cur)
        {
            nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }
    bool isPalindrome(ListNode* head) {
        //得到中间节点
        ListNode* middle = Getmidddle(head);
        ListNode* head2 = ReverseLink(middle);
        while(head2)
        {
            if(head->val != head2->val)
                return false;
            head = head->next;
            head2 = head2->next;
        }
        return true;
    }
};

python

python 复制代码
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):

    # 找到中间结果,对于奇数,直接就是中间
    # 对于偶数,则是中间的右边节点
    def GetMiddleNode(self, head):
        """
        :type head: Optional[ListNode]
        :rtype: ListNode
        """
        slow, fast = head, head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        return slow

    # 反转链表
    # 反转从中间节点到原本链表之间的关系,比如1->2->3->4->5->6
    # 反转后:1->2->3->4<-5<-6
    def reverseLink(self, head):
        """
        :type head: Optional[ListNode]
        :rtype: ListNode
        """
        pre, cur= None, head
        while cur:
            nxt = cur.next
            cur.next = pre
            pre = cur
            cur = nxt
        return pre
        

    def isPalindrome(self, head):
        """
        :type head: Optional[ListNode]
        :rtype: bool
        """
        #1. 找到中间节点
        middle = self.GetMiddleNode(head)
        #2. 反转链表
        head2 = self.reverseLink(middle)
        while head2:
            if head.val == head2.val:
                head = head.next
                head2 = head2.next
            else:
                return False
        return True
            


        

参考

O(1) 空间做法:寻找中间节点+反转链表(Python/Java/C++/C/Go/JS/Rust)

相关推荐
海绵宝宝转agent25 分钟前
leetCode100算法开源笔记分享
笔记·算法
写后端的胖头鱼1 小时前
时间复杂度 & 空间复杂度
java·数据结构·算法·时间复杂度·空间复杂度
hahaha60161 小时前
黑体轨迹和色温--光源白点
人工智能·嵌入式硬件·算法·计算机视觉
海绵宝宝转agent1 小时前
基于Redis ZSet+AOP+注解实现限流注解算法
数据库·redis·算法
50万马克的面包2 小时前
顺序表和链表_精华知识点_CSDN博客
数据结构·链表
All for pursuit.2 小时前
【回溯-7】494.目标和
数据结构·c++·算法·leetcode
白杨尚青2 小时前
C++入门篇(十三):vector(上)——动态数组:构造、空间增长与迭代器失效
开发语言·c++·笔记·算法·stl
Jasmine_llq2 小时前
《P17461 [GESP202609 八级] 生成树计数》
算法·栈·tarjan 算法·边双连通分量·深度优先搜索 dfs·tarjan 保存当前路径节点·模乘法
Jasmine_llq2 小时前
《P17462 [GESP202609 八级] 末班车》
算法·dijkstra 算法·最大化版本,求最长可行值·建反向图(逆图 / 反转边)·多源 dijkstra 思想·对每个终点单独跑一遍djst·离线预处理 + 在线查询
the3clipse3 小时前
H.265熵编码核心:CABAC自适应二进制算术编码详解——如何将语法元素高效压缩为比特流
人工智能·算法·视频编码·h.265·hevc·cabac·cavlc