力扣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)

相关推荐
I_belong_to_jesus8 小时前
C++关于分支预测的优化1
开发语言·c++·算法
Code_Solitude15 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司16 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
文丑颜不良啊17 小时前
LeetCode2821~2840题目解析
java·leetcode
YLCHUP18 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
思麟呀18 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落20 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
Pniubi20 小时前
力扣24. 两两交换链表中的节点(递归)
算法·leetcode·链表
꧁细听勿语情꧂21 小时前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法