234. Palindrome Linked List(python+cpp)

题目:

Given a singly linked list, determine if it is a palindrome.
Example 1:

Input: 1->2 
Output: false 
**Example 2:**

Input: 1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?

解释:
判断一个;链表是不是回文,但是链表的指针并不能翻转,怎么办呢/
利用快慢指针先找到中间的位置(假设链表长度为n,则slow指向的是n/2+1(index从1开始),也就是后半段的 第一个结点),把链表从中间位置开始翻转,再两个指针,一个指向mid一个指向head,开始遍历,如果每个值都一样的话说明是回文。需要考虑链表的长度是奇数或者偶数的情况。
额,当然也可以把链表的元素保存到一个数组中,再判断是不是回文,但是这样的话空间复杂度就不是 O(1)了
python代码:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if not head or not head.next:
            return True
        slow,fast=head,head
        middle_pre=slow
        while fast and fast.next:
            middle_pre=slow
            slow=slow.next
            fast=fast.next.next
        #middle_pre保存第一部分的最后一个结点
        p=middle_pre.next
        cur_pre=None
        while p:
            cur_next=p.next
            p.next=cur_pre
            cur_pre=p
            p=cur_next
        middle_pre.next=cur_pre
        p_middle=middle_pre.next
        p_head=head
        while p_head!=middle_pre.next:
            if p_head.val!=p_middle.val:
                return False
            p_head=p_head.next
            p_middle=p_middle.next
        return True

c++代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (!head ||!head->next)
            return true;
        ListNode *fast=head,*slow=head;
        //middle_pre指向前半段的最后一个元素
        ListNode *middle_pre=slow;
        while(fast &&fast->next)
        {
            middle_pre=slow;
            slow=slow->next;
            fast=fast->next->next;
        }
        //原地翻转后半部分链表的工作指针
        ListNode*cur=middle_pre->next;
        ListNode*cur_pre=NULL;
        //下面是原地翻转单链表的经典写法
        while(cur)
        {
            ListNode*cur_next=cur->next;
            cur->next=cur_pre;
            cur_pre=cur;
            cur=cur_next;
        }
        //此时,cur_pre保存翻转后的链表的头结点,这里是合并
        middle_pre->next=cur_pre;
        //接下来是比较,注意,后半段的元素有可能比前半段的元素多一个
        //所以while循环的第一个条件是必须的
        ListNode* p_head=head;
        ListNode* p_middle=cur_pre;
        while(p_head!=middle_pre->next)
        { 
            if(p_head->val!=p_middle->val)
                return false;
            p_head=p_head->next;
            p_middle=p_middle->next;
        }
        return true;
    }
};

总结:
注意最后比较的时候的判断条件只有一个即可,因为后半段的个数肯定>=前半段个数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值