说明:转载请注明出处http://blog.csdn.net/yuanwei1314/article/details/40828455
题目:
判断一条单向链表是不是"回文"
思路一:采用快慢指针,慢指针入栈,当快指针为NULL时,出栈和慢指针比较即可。时间复杂度O(n),空间复杂度O(n)。
优点:比较好实现,且没有修改链表
缺点:需要分配内存
#include <stdio.h>
#include <stdlib.h>
#include <stack>
typedef int elem;
typedef struct node
{
elem data;
struct node *next;
}LNode, *LINKLIST;
/*采用快慢指针方式,将慢指针的结点添加到栈中
当快指针到NULL时,将慢指针的结点与快指针比较即可*/
bool isPalindromeList(LINKLIST list)
{
LNode* fast = list->next;
LNode* slow = list->next;
bool flag = false;/*奇偶判断需要*/
stack<elem> s;
while (fast != NULL)
{
s.push(slow->data);
/*快指针走两步*/
fast = fast->next;
slow = slow->next;
if (fast != NULL)
{
fast = fast->next;
}
else
{
flag = true;
}
}
/*如果是奇结点,出栈一个*/
if (flag)
{
s.pop();
}
/*慢指针和栈直接比较*/
while (slow!=NULL && !s.empty())
{
if (slow->data != s.top())
{
return false;
}
slow = slow->next;
s.pop();
}
return true;
}
/*采用尾插法,创建单链表*/
void createList(LINKLIST list, elem data)
{
LNode* p = list;
LNode* newNode;
while (p->next != NULL)
{
p = p->next;
}
newNode = (LNode*)malloc(sizeof(LNode));
newNode->next = NULL;
newNode->data = data;
p->next = newNode;
}
/*打印单链表*/
void printList(LINKLIST list, void(*print)(elem))
{
LNode* p = list->next;
while (p != NULL)
{
print(p->data);
p = p->next;
}
printf("\n");
}
/*打印结点值*/
void printElem(elem data)
{
printf("%d\t", data);
}
int main()
{
LINKLIST list = NULL;
elem data[] = {1,2,3,3,2,1};
int i;
list = (LINKLIST)malloc(sizeof(LNode));
list->next = NULL;
list->data = 0;
for (i=0; i<6; i++)
{
createList(list, data[i]);
}
printList(list, printElem);
if (isPalindromeList(list))
{
printf("TRUE\n");
}
else
{
printf("FALSE\n");
}
return 0;
}
思路二:采用快慢指针,当快指针为NULL时,翻转慢指针。比较前半部分链表和翻转链表即可。时间复杂度O(n),空间复杂度O(1)。
优点:节约空间
缺点:改变了链表的值
#include <stdio.h>
#include <stdlib.h>
#include <stack>
typedef int elem;
typedef struct node
{
elem data;
struct node *next;
}LNode, *LINKLIST;
LNode* reverseLink(LNode* begin, LNode* end)
{
LNode* pre = NULL;
LNode* q;
LNode* p = begin;
LNode* head = NULL;
while (p != end)
{
q = p->next;
if (q == end)
{
head = p;
}
p->next = pre;
pre = p;
p = q;
}
return head;
}
/*采用快慢指针方式,当到中间时逆转后半部分指针
挨个比较,如果满足相同则返回true*/
bool isPalindromeList(LINKLIST list)
{
LNode* slow = list->next;
LNode* fast = list->next;
LNode* p = list->next;
LNode* head = NULL;
while (fast != NULL)
{
slow = slow->next;
fast = fast->next;
if (fast != NULL)
{
fast = fast->next;
}
}
/*获取翻转过后的头结点*/
head = reverseLink(slow, NULL);
while (p!=NULL && head!=NULL)
{
if (p->data != head->data)
{
return false;
}
p = p->next;
head = head->next;
}
return true;
}
/*采用尾插法,创建单链表*/
void createList(LINKLIST list, elem data)
{
LNode* p = list;
LNode* newNode;
while (p->next != NULL)
{
p = p->next;
}
newNode = (LNode*)malloc(sizeof(LNode));
newNode->next = NULL;
newNode->data = data;
p->next = newNode;
}
/*打印单链表*/
void printList(LINKLIST list, void(*print)(elem))
{
LNode* p = list->next;
while (p != NULL)
{
print(p->data);
p = p->next;
}
printf("\n");
}
/*打印结点值*/
void printElem(elem data)
{
printf("%d\t", data);
}
/*TEST*/
int main()
{
LINKLIST list = NULL;
elem data[] = {1,2,3,2,1,5};
int i;
list = (LINKLIST)malloc(sizeof(LNode));
list->next = NULL;
list->data = 0;
for (i=0; i<6; i++)
{
createList(list, data[i]);
}
printList(list, printElem);
if (isPalindromeList(list))
{
printf("TRUE\n");
}
else
{
printf("FALSE\n");
}
return 0;
}