最新学习前google工程师王争大佬的《数据结构与算法之美》,06|链表(上):如何实现LRU缓存淘汰算法,
这章节课后习题:如何判断一个字符串是否是回文字符串的问题,如果字符串是通过单链表来存储,那么如何判断是一个回文串呢?
以下是思路:
使用快慢两个指针找到链表中点,慢指针走1步,快指针走2步。每次慢指针走过的路都要逆序,使得链表前半部分反序,最后再比
较两侧链表是否相等时,顺便逆序前半段,复原链表。注意区分奇偶。
时间复杂度:O(n)
空间复杂度:O(1)
代码(经过自己验证过,如果有不足请各位大佬们留言指出~):
#include <iostream> using namespace std; struct Node { int a; Node * pNext; Node() :a(0) ,pNext(NULL) { } Node(int par) :a(par) ,pNext(NULL) { } }; void NewHead(Node ** pHead) { *pHead = new Node(); } void HeadInsert(Node * pHead, int nNum) { if (!pHead) { return; } Node * pTempNode = pHead->pNext; pHead->pNext = new Node(nNum); if (pTempNode) { pHead->pNext->pNext = pTempNode; } } void ShowAll(Node * pHead) { if (!pHead) { return; } Node * pTempNext = pHead->pNext; cout<< "------start-----"<<endl; while (pTempNext) { cout<< pTempNext->a; pTempNext = pTempNext->pNext; } cout<<endl; cout<< "------end-----"<<endl; } bool HuiWenString(Node * pHead) { if (!pHead || !pHead->pNext) { return true; } bool bIsHuiWen = true; Node * pPrev = pHead; //始终是慢指针(pSlow)前个节点,链表前半部分逆序的头节点,最后要与pSlow比较 Node * pTemp = NULL; //临时变量 Node * pSlow = pHead; //慢指针 Node * pFast = pHead; //快指针,用于帮助慢指针定位中间点。 while (pFast && pFast->pNext) //找中间节点 { pFast = pFast->pNext->pNext; //逆序前半段 pTemp = pPrev; pPrev = pSlow; pSlow = pSlow->pNext; pPrev->pNext = pTemp; } Node * pPrevNext = pSlow;//pPrev的后一个节点,用于还原前半部分的逆序链表 if(!pFast)//奇 { pSlow = pSlow->pNext; } while (pSlow) { if (bIsHuiWen) { if (pSlow->a != pPrev->a) { bIsHuiWen = false; } } //再次逆序前半段,恢复链表 pTemp = pPrev->pNext; pPrev->pNext = pPrevNext; pPrevNext = pPrev; pPrev = pTemp; pSlow = pSlow->pNext; } pHead->pNext = pPrevNext; return bIsHuiWen; } int main() { Node * pHead = NULL; NewHead(&pHead); //测试代码 for (int i = 1; i<9; i++) { HeadInsert(pHead, i); } for (int i = 9; i>0; i--) { HeadInsert(pHead, i); } ShowAll(pHead); bool bIsHuiWen = HuiWenString(pHead); cout<<"is huiwen "<< bIsHuiWen<<endl; ShowAll(pHead); return 0; }