這是一道好題,思路雖然有,但是提交之後總是有資料過不了,又按照資料改改改,最後代碼都沒法看了。收到的教訓是如果必須為自己的代碼加上很多很多特殊的限定,來過一些特殊的資料的話,說明代碼本身有很大的漏洞。
這道題,我想到了要用兩個指標儲存亂序的節點,甚至想到了用一個pre指標來儲存前面一個節點,但是問題出在哪裡呢?我覺得應該是自己對樹的遍曆理解的不夠深刻。既然知道了二叉搜尋樹一定是用中序遍曆的,那麼程式的架構應該馬上寫的出來,先左子樹,再根,再右子樹,那你說什麼時候更新pre指標呢,當然是訪問根節點的時候,如果把每次返回的節點作為接下來考慮的左子樹,其實並不是一種中序遍曆,更像是前序走訪。還有一點,我當時總是想單獨的找出這兩個亂序的節點,然後加了很多特殊情況考慮如果他們兩個相鄰怎麼辦。其實這不是很好解決的嗎,因為一共只有兩個節點亂掉了,那麼一開始不滿足條件的那對節點肯定包含了其中一個,而且是較大的那個是亂掉的。往後的話,如果又出現了這個問題,一定是較小那個,不用加任何特殊情況的考慮。
代碼非常簡潔,好慚愧:
TreeNode *e1, *e2, *pre;void inorder(TreeNode *root){ if(root == NULL) return; if(root->left) inorder(root->left); if(pre&&pre->val>root->val){ if(e1 == NULL) e1 = pre, e2 = root; else e2 = root; } pre = root; if(root->right) inorder(root->right); return;} class Solution {public: void recoverTree(TreeNode *root) { pre = NULL, e1 = NULL, e2 = NULL; inorder(root); swap(e1->val, e2->val); return; }};