check whether a single linked list is palindrome. for example: 1->2->1,return ture. and 1->2->3->1 return false; and can you resolve it in linear time. 如果是数组那用递归和非递归都很好解决了,但是链表貌似有点麻烦。
首先给出思路就是:先找到链表中间的节点,记得区分链表中节点个数是奇数还是偶数。然后把链表的前一半节点放入栈之中,之后从中间节点的后一个节点开始,此节点和栈顶节点所存储的值进行比较,如果相等则继续进行后续比较,直到链表结尾。如果中间出现不相等的情况,则不是回文。 那么,怎么样找到链表的中间节点呢。一个方法是遍历一遍链表,统计它的节点个数,然后取个数的中间值(记得区奇数偶数)。这样再次遍历就会找到中间的节点。说道这里应该有思路了,但是还有一个更好的解法,就是设定双指针。
#include<iostream>
#include<stack>
using namespace std;
typedef struct node{
int data;
struct node *next;
}LinkNode, *LinkList;
void create_list(LinkList *L, int *a, int n) {
int i = 0;
LinkNode *p = NULL;
LinkNode *temp = NULL;
while(i < n) {
p = (LinkNode*)malloc(sizeof(LinkNode));
p->data = a[i];
p->next = NULL;
if(*L == NULL) {
*L = p;
} else {
temp->next = p;
}
temp = p;
i++;
}
}
int is_palindrome(LinkList head) {
int length = 0;
int mid = 0;
int i;
stack<LinkNode*> m_stack;
LinkNode *p = head;
LinkNode *temp = NULL;
int flag = 1;
while(p) {
length++;
p = p->next;
}
if(length %2 == 0) {
mid = length / 2;
} else {
mid = length / 2 + 1;
}
p = head;
i = 1;
while(i <= mid - 1) {
m_stack.push(p);
p = p->next;
i++;
}
if(length % 2 == 0) {
m_stack.push(p);
}
p = p->next;
while(!m_stack.empty() && p) {
temp = m_stack.top();
m_stack.pop();
if(temp->data != p->data) {
flag = 0;
break;
}
p = p->next;
}
return flag;
}
void main() {
int a[] = {1, 2, 3, 4, 5, 4, 3, 2, 1};
int n = sizeof(a) / sizeof(int);
LinkList head = NULL;
create_list(&head, a, n);
if(is_palindrome(head)) {
cout << "yes" << endl;
} else {
cout << "no" << endl;
}
getchar();
}
双指针的解法:
bool isPanli(LinkList head)
{
stack<LinkNode*> stk;
LinkNode* slow = head;
LinkNode* fast = head;
bool flag = false;
while (fast) {
stk.push(slow);
slow = slow->next;
fast = fast->next;
if (fast) {
fast = fast->next;
} else
flag = true;
}
if (flag)
stk.pop();
while (!stk.empty()) {
if (stk.top()->data == slow->data){
stk.pop();
slow = slow->next;
}
else
return false;
}
return true;
}