題目:給定一個單向鏈表,判斷它是否是迴文鏈表(即從前日後讀和從後往前讀是同樣的)。原題見下圖,還要求了O(n)的時間複雜度O(1)的空間複雜度。數組
個人思考:spa
1,一看到這個題目,大腦立刻想到的解決方案就是數組。遍歷鏈表,用數組把數據存下來,而後再進行一次遍歷,同時用數組反向地與之比較,這樣就能夠判斷是否迴文。這個方法時間複雜度是O(n),達到了要求,然而空間複雜度顯然不知足要求。因此,開數組這一類的方法顯然不是最佳的。3d
2,既然要知足O(1)的空間複雜度,我就想到了用一個變量來存儲這些數據,剛好題目給出的數據也是整型。具體思路就是用一個long int:sum來存儲這些數據,第一次遍歷:第一個節點的數據乘1加到sum,第二個節點的數據乘2加到sum,第三個節點的數據乘3加到sum……;而後再反向進行第二次遍歷,sum減去最後一個節點的數據和1的乘積,sum減去倒數第二個節點的數據和2的乘積……。只要看最後的sum是否爲0就能夠判斷鏈表是否迴文。固然,在第一次遍歷的時候須要一邊遍歷一邊逆置該鏈表,才能進行第二次遍歷。貼上代碼:指針
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */
class Solution { public: bool isPalindrome(ListNode* head) { ListNode *point1, *point2, *point3; point3 = point2 = head; point1 = NULL; long int sum = 0; int n = 1; if(head == NULL || head->next == NULL return true; while(point3->next != NULL)//第一次遍歷,取值並逆置 { sum += n*point3->val; n++; point3 = point3->next; point2->next = point1; point1 = point2; point2 = point3; } sum += n*point3->val; point2->next = point1; n = 1; while(point2 != NULL)//第二次遍歷 { sum -= n*point2->val; n++; point2 = point2->next; } if(sum == 0) return true; else
return false; } };
提交的結果顯示這個方法在題目的條件範圍內是可行的:code
仔細一想,若是節點中的數據是字符,是浮點數怎麼辦?這時這個方法的侷限性就顯現出來了。blog
3,不能用一個整型來存儲字符這類的信息,那隻能直接比較節點裏的信息了。怎麼比較?咱們知道迴文鏈表的特色就是對稱,那麼要判斷是否迴文就能夠用兩個指針指向對稱的節點,看裏面的信息是否同樣。即對稱的位置是否有對稱的信息。因爲是單向鏈表,不能同時用兩個指針從頭尾向內部遍歷取值比較。那麼就考慮從鏈表中間開始,用兩個指針向兩頭遍歷取值比較,顯然這也須要進行鏈表逆置。it
具體的作法就是先遍歷一次鏈表獲得鏈表長度。而後第二次遍歷到鏈表中間,並在遍歷的時候進行逆置。而後兩個指針分離,分別向兩個端點移動,同時進行比較,數據相同則繼續,數據不一樣則直接返回false。直到遍歷完成,最後返回true。代碼:io
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */
class Solution { public: bool isPalindrome(ListNode* head) { int lenth, i; ListNode *point1, *point2, *point3; point3 = point2 = head; point1 = NULL; lenth = 0; if(head == NULL || head->next == NULL) return true; while(point3 != NULL)//取得長度 { point3 = point3->next; lenth++; } for(i = 0;i < (lenth / 2);i++)//遍歷到中間,並逆置 { point3 = point2->next; point2->next = point1; point1 = point2; point2 = point3; } if((lenth % 2) == 1) point3 = point3->next; while(point3 != NULL && point1 != NULL)//兩個指針開始向兩頭移動,取值比較 { if(point3->val != point1->val) return false; point3 = point3->next; point1 = point1->next; } return true;//比較中沒有發現不一樣值,則爲迴文鏈表 } };
最後的結果也證實這個方法是可行的:class
比起上一種方法,這個方法沒有存儲信息的操做,因此沒必要擔憂用什麼數據類型去存儲,也不用擔憂數據的溢出,適用的範圍固然也就更大。變量
若博文中有什麼不正確的地方歡迎你們指正,謝謝~