您的位置:首页 > 其它

[LeetCode-234] Palindrome Linked List(回文链表、链表中间节点查找)

2015-10-08 21:46 477 查看
Given a singly linked list, determine if it is a palindrome.

Follow up:

Could you do it in O(n) time and O(1) space?

【分析】

找到链表中点,拆分后,逆转后半个链表,然后两个链表同时顺序遍历一次。

不过唯一需要注意的是,当链表长度为奇数,我们需要先将链表中点往下移动一个节点后在反转半个链表

比如{1->2->3->2->1} 我们找到链表中点3之后需要向下移动一个节点{1->2->3}只需要比较1->2 这两个节点是否相等

时间复杂度O(n),空间复杂度O(1)

代码如下:

struct LinkNodeMid {
struct ListNode *LastNode;
struct ListNode *NodeMid;
};
/*无头结点*/
struct ListNode* reverseList(struct ListNode* head)
{
if((head == NULL) || (head->next==NULL))  //链表为空,或只有一个结点(无需反转),直接返回
return head;

struct ListNode *pre = NULL;//前一个
struct ListNode *cur = NULL;//当前
struct ListNode *ne = NULL;//后一个

pre = head;         //将前面几个节点的地址依次保存在新定义的结构体指针
cur = head ->next;

while(cur)
{
ne = cur->next;  //如果当前节点不为空,则将其指针域赋给ne指针
cur->next = pre; //直接将两个指针的指向反转
pre = cur;       //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
cur = ne;
}
head->next = NULL;//将原来的第一个节点的指针域赋为空,作为尾节点
head = pre;      //将原来的尾节点变成新链表的第一个节点
return head;
}

struct LinkNodeMid* getLinkNodeMid(struct ListNode* head)
{
/*at least two nodes*/
struct ListNode* slow = head;
struct ListNode* fast = head;
struct LinkNodeMid* LinkNodeMidinfo = (struct LinkNodeMid*)malloc(sizeof(struct LinkNodeMid));
/*Fast Linknode move double step one time,
slow Linknode move one step,
then the slow is the mid head*/
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;/*even is NULL,then end the cycle*/
}

LinkNodeMidinfo->LastNode = fast;
LinkNodeMidinfo->NodeMid = slow;

return LinkNodeMidinfo;
}

bool isPalindrome(struct ListNode* head)
{
if(!head||!head->next)
return true;
struct ListNode* phead = head;
struct LinkNodeMid* LinkNodeMidinfo= getLinkNodeMid(phead);
struct ListNode* pReverseListhead = NULL;

/*if LastNode is NULL,then the length LinkNode is odd,otherwise is even*/
if(LinkNodeMidinfo->LastNode) {
pReverseListhead = reverseList(LinkNodeMidinfo->NodeMid->next);
}
else {
pReverseListhead = reverseList(LinkNodeMidinfo->NodeMid);
}

while(phead && pReverseListhead) {
if(phead->val != pReverseListhead->val) {
free(LinkNodeMidinfo);
return false;
}
phead = phead->next;
pReverseListhead = pReverseListhead->next;
}
free(LinkNodeMidinfo);
return true;
}


完整的代码如下:

// LeetCode234-Palindrome Linked List.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
/**
* Definition for singly-linked list.
**/
struct ListNode {
int val;
struct ListNode *next;
};
/*1.Get LinkNodeMid by NodeMid;
2.LastNode is to distinguish the length LinkNode is odd or even
if LastNode is NULL,then the length LinkNode is odd,otherwise is even*/
struct LinkNodeMid {
struct ListNode *LastNode;
struct ListNode *NodeMid;
};
struct ListNode* CreatLink(int aData[],int len)
{
if(!aData)
return NULL;
struct ListNode *head = NULL;
struct ListNode *p = NULL;
struct ListNode *Link= NULL;
/*第一个节点*/
head = (struct ListNode *)malloc(sizeof(struct ListNode));
head->val = aData[0];
head->next = NULL;
// aData ++;
Link = head; /*保存头结点*/
int i = 1;

while(i < len) {
p = (struct ListNode *)malloc(sizeof(struct ListNode));
p->val = aData[i];
head->next = p;
head = p;
i ++;
}

head->next = NULL;
return Link;
}

void printLink(struct ListNode *head)
{
while(head) {
printf("%d",head->val);
head = head->next;
}
printf("\n");
}

/*无头结点*/
struct ListNode* reverseList(struct ListNode* head)
{
if((head == NULL) || (head->next==NULL))  //链表为空,或只有一个结点(无需反转),直接返回
return head;

struct ListNode *pre = NULL;//前一个
struct ListNode *cur = NULL;//当前
struct ListNode *ne = NULL;//后一个

pre = head;         //将前面几个节点的地址依次保存在新定义的结构体指针
cur = head ->next;

while(cur)
{
ne = cur->next;  //如果当前节点不为空,则将其指针域赋给ne指针
cur->next = pre; //直接将两个指针的指向反转
pre = cur;       //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
cur = ne;
}
head->next = NULL;//将原来的第一个节点的指针域赋为空,作为尾节点
head = pre;      //将原来的尾节点变成新链表的第一个节点
return head;
}

struct LinkNodeMid* getLinkNodeMid(struct ListNode* head)
{
/*at least two nodes*/
struct ListNode* slow = head;
struct ListNode* fast = head;
struct LinkNodeMid* LinkNodeMidinfo = (struct LinkNodeMid*)malloc(sizeof(struct LinkNodeMid));
/*Fast Linknode move double step one time,
slow Linknode move one step,
then the slow is the mid head*/
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;/*even is NULL,then end the cycle*/
}

LinkNodeMidinfo->LastNode = fast;
LinkNodeMidinfo->NodeMid = slow;

return LinkNodeMidinfo;
}

bool isPalindrome(struct ListNode* head)
{
if(!head||!head->next)
return false;
struct ListNode* phead = head;
struct LinkNodeMid* LinkNodeMidinfo= getLinkNodeMid(phead);
struct ListNode* pReverseListhead = NULL;

/*if LastNode is NULL,then the length LinkNode is odd,otherwise is even*/
if(LinkNodeMidinfo->LastNode) {
pReverseListhead = reverseList(LinkNodeMidinfo->NodeMid->next);
}
else {
pReverseListhead = reverseList(LinkNodeMidinfo->NodeMid);
}

while(phead && pReverseListhead) {
if(phead->val != pReverseListhead->val) {
free(LinkNodeMidinfo);
return false;
}
phead = phead->next;
pReverseListhead = pReverseListhead->next;
}
free(LinkNodeMidinfo);
return true;
}

int _tmain(int argc, _TCHAR* argv[])
{

int a[] = {1,1,2,1,1};
struct ListNode *head1 = NULL;
head1 = CreatLink(a,sizeof(a)/sizeof(int));
//printLink(head1);
printf("[%d] %d\n",__LINE__,isPalindrome(head1));
free(head1);
getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LeetCode