Palindrome Linked List

题目234:Palindrome Linked List

题目描述:
Given a singly linked list, determine if it is a palindrome.
Could you do it in O(n) time and O(1) space?
题目分析:
给一个链表判断是否是回文,时间复杂度O(n) ,空间复杂度O(1)指的是额外空间相对于输入数据量来说是常数(《严书》),不随着输入规模n的变化而变化。
排除用栈的方法,压入链表中一半的元素,再一一弹栈,比较链表中后面的元素,因为栈作为辅助空间,随着输入规模n的增大而增大。
《剑指offer》面试题5:从尾到头打印链表
有些类似,这个题目可以分为改变链表结构和不改变链表结构两种。
1. 改变链表的结构:将链表后半部分的元素转置,然后一一比较,判断是否是回文;
2. 不改变链表的结构:

1. 将链表的后半部分元素转置

/**
 * 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 == 0 || head->next == 0)
            return true;
        ListNode *fast, *slow;
        fast = head;
        slow = head;
        while (fast->next && fast->next->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        ListNode *cur, *pre, *pnext;
        pre = slow->next;
        cur = pre;
        pnext = pre->next;
        pre->next = 0;
        while (pnext) {
            cur = pnext;
            pnext = pnext->next;
            cur->next = pre;
            pre = cur;
        }
        slow->next = cur;
        while (cur) {
            if (cur->val != head->val) {
                return false;
            } 
            cur = cur->next;
            head = head->next;
        }
        return true;
    }
};

其实可以将链表后半部分元素转置的过程,定义为一个函数,在判断是否回文结束,再重新将链表后半部分转置回来,链表结构不变化。

快慢指针
链表题目常用快慢指针。快慢指针,快和慢指的是指针每次移动速度的快慢。比如,快指针,每次沿链表移动2,慢指针,每次沿链表移动1。
举几个例子看快慢指针的应用:
(1)判断单链表是否为循环链表:如果单链表有循环链表,那么快指针一定会遇到慢指针,可能第一次不能相遇,但一定会遇到;
(2)在有序链表中寻找中位数:注意是有序链表,快指针速度是慢指针速度的2倍,还要考虑有序链表中结点个数是奇数还是偶数。如果快指针移动x次后指向链表中最好一个结点(1+2x),则链表有奇数个结点,直接返回慢指针指向的结点;如果快指针指向倒数第二个结点,说明链表结点个数是偶数,这时可以根据要求返回上中位数或下中位数或(上中位数+下中位数)的一半。
(3)判断两个链表是否交叉:如果交叉,则从交叉点开始的后面结点两个链表重合,第一次分别遍历两个链表的长度,设置快慢指针,快指针先走。

2.

参考:
[1] http://www.cnblogs.com/hxsyl/p/4395794.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值