在Y公司的筆試題中遇見了這樣一個題目:
一個單鏈表,如何使用O(1)的空間複雜度判定其是否為對稱鏈表,例如A->B->C->T->C->B->A就是一個對稱鏈表。
首先最自然的就能想到N^2的演算法:
尋找1號和最後一個是否相同,再尋找2號和倒數第二個。。。尋找i和N-i是否相同。
但是這個演算法明顯不是最優解答。
對鏈表的分析之後可以看出,如果找到中間節點,從中間節點斷開鏈表,反向鏈表後部的部分,再一起遍曆兩個鏈表,這樣的演算法的時間複雜度一定是N,而反向鏈表所需要的空間開銷也為常數。
代碼如下:
#include <iostream>using namespace std;struct Node{int data;Node *next;};Node *head;int initial(){head = new Node;head->data = 0;head->next = NULL;Node *pNode = head;for (int i=1;i<6;++i){pNode->next = new Node;pNode = pNode->next;pNode->data = i;pNode->next = NULL;}for (int i=5;i>=0;--i){pNode->next = new Node;pNode = pNode->next;pNode->data = i;pNode->next = NULL;}return 0;}void deleteList(){Node *pNode = head;while(pNode){Node *q = pNode->next;delete pNode;pNode = q;}}void printList(Node *head){Node *pNode = head;while(pNode){cout<<pNode->data<<endl;pNode = pNode->next;}}Node* reverseList(Node *head){Node *pNode = head->next, *pNext = NULL;head->next = NULL;while (pNode){pNext = pNode->next;pNode->next = head;head = pNode;pNode = pNext;}return head;}bool yahooList(){int len = 0;Node *pNode = head;//get lengthwhile (pNode){++len;pNode = pNode->next;}if (1 == len){return true;}//找中點,如果是奇數個則指向中點的下一個元素bool bOdd = len & 0x00000001;//odd num delete middle numberint mid = len>>1;int i = 0;pNode = head;while(i++ != mid)pNode = pNode->next;if (bOdd)pNode = pNode->next;Node *pOther = reverseList(pNode);#ifdef _DEBUGcout<<"the reverse list is:"<<endl;printList(pOther);#endif // _DEBUG//順序比較pNode = head;while (pOther && pNode){if (pOther->data != pNode->data){return false;}pOther = pOther->next;pNode = pNode->next;}return true;}int main(){initial();printList(head);cout<<yahooList()<<endl;return 0;}