方法一:對陣列進行排序
演算法:
按中序遍歷樹,遍歷之後的陣列應該是幾乎排序的列表,其中只有兩個元素被交換
再次遍歷樹,將值x的節點改為y,將值y的節點改為x
**:
/**
* definition for a binary tree node.
* public class treenode
* }*/class
solution
public
int[
](list
nums)
}return
newint
;}public
void
recover
(treenode r,
int count,
int x,
int y)
recover
(r.left, count, x, y)
;recover
(r.right, count, x, y);}
}public
void
recovertree
(treenode root)
}
執行結果:
複製到分析:
時間複雜度:最壞o(n),最好o(1)
空間複雜度:o(n)
優化思路:
在方法一中,我們討論了這個難題的三個簡單子問題:
構造中序遍歷序列
在幾乎排序的數列中查詢兩個交換的元素
在陣列中交換兩個節點的值
事實上,我們可以將上面的三個步驟簡化成兩步:
合併步驟一和步驟二,即在中序遍歷時確定交換的元素
交換節點的值
以下的方法區別只在於實現中序遍歷的演算法
方法二:迭代中序遍歷
演算法:
在這裡,我們通過迭代構造中序遍歷,並在一次遍歷中找到交換的節點。
迭代順序很簡單:盡可能的向左走,然後向右走一步,重複一直到結束。
若要找到交換的節點,就記錄中序遍歷中的最後乙個節點 pred(即當前節點的前置節點),並與當前節點的值進行比較。如果當前節點的值小於前置節點 pred 的值,說明該節點是交換節點之一。
交換的節點只有兩個,因此在確定了第二個交換節點以後,可以終止遍歷。
這樣,就可以直接獲取節點(而不僅僅是它們的值),從而實現 o(1)的交換時間,大大減少了步驟 3 所需的時間。
**:
/**
* definition for a binary tree node.
* public class treenode
* }*/class
solution
public
void
recovertree
(treenode root)
root = stack.
removelast()
;if(pred != null && root.val < pred.val)
pred = root;
root = root.right;
}swap
(x, y);}
}
執行結果:
複雜度分析:
時間複雜度:最好o(1),最壞(交換節點之一是最右邊的葉節點)o(n)
空間複雜度:o(h),h指的是樹的高度
方法三:遞迴中序遍歷
演算法:
遵循 left 到 node 到 right 方向
即對左子節點進行遞迴呼叫,然後判斷該節點是否被交換,再對右子節點執行遞迴呼叫
**:
/**
* definition for a binary tree node.
* public class treenode
* }*/class
solution
public
void
(treenode root)
pred = root;
(root.right);}
public
void
recovertree
(treenode root)
}
執行結果:
複雜度分析:
時間複雜度:最好o(1),最壞o(n)
空間複雜度:o(h)
方法四:mirris中序遍歷
演算法:如果沒有鏈結,設定連線並走向左子樹。
如果有連線,斷開連線並走向右子樹。
如果該節點沒有左孩子,即沒有左子樹,則我們直接走向右子樹。
**:
/**
* definition for a binary tree node.
* public class treenode
* }*/class
solution
public
void
recovertree
(treenode root)
// break link predecessor.right = root
// link is broken : time to change subtree and go right
else
pred = root;
predecessor.right = null;
root = root.right;}}
// if there is no left child
// then just go right.
else
pred = root;
root = root.right;}}
swap
(x, y);}
}
執行結果:
複雜度分析:
時間複雜度:o(n),訪問每個節點兩次
空間複雜度:o(1)
吾之生也有涯,而知也無涯
冥想第二十四天
還有乙個需要提高的地方就是 慢一點,以往自己對成功和只是追求的太急切。一急切就亂了節奏,適當的急切是必要的 放輕鬆全身都是最舒服的狀態。平靜的內心讓自己能面對生活的困難。感謝自己,感謝家人,感謝朋友,感謝一切。不責怪自己,一天比一天進步就好。慢慢來。下午和客戶積極的溝通,全身心的投入,發現一點也不困...
連續總結第二十四天
11.4 康鑫 連續總結第二十四天 今天學習了課本上有關陣列的知識,陣列與指標。1,指標運算包括a,賦值運算 b,算術運算 c,關係運算 d,邏輯運算。2 一維陣列 a 與指標 p 3,二維陣列 b,m行n列 與指標。4,字元陣列 s 與指標 ps 5,指標陣列 完成了課本的例題,通過程式設計實現二...
2017 8 23暑假集訓第二十四天
今天一共a了兩道題 1001.1002 比較簡單的?1001做了一上午 一直在繞一點 當輸入字元m後,要輸入五個數字 用scanf輸入的 但是!卻只寫了四個 d!然後就一直在找bug!找了一上午。我很疑惑,為什麼編譯能過!提交還是莫名其妙的wa!一直在懷疑自己!下午 睡過頭了 來的晚了 1007看了...