Hi 你們好,我是張小豬。歡迎來到『寶寶也能看懂』系列之 leetcode 題解。node
這裏是第 169 期的第 2 題,也是題目列表中的第 1305 題 -- 『All Elements in Two Binary Search Trees』git
Given two binary search trees root1
and root2
.github
Return a list containing all the integers from both trees sorted in ascending order.shell
Example 1:數組
Input: root1 = [2,1,4], root2 = [1,0,3] Output: [0,1,1,2,3,4]
Example 2:數據結構
Input: root1 = [0,-10,10], root2 = [5,1,7,0,2] Output: [-10,0,0,1,2,5,7,10]
Example 3:post
Input: root1 = [], root2 = [5,1,7,0,2] Output: [0,1,2,5,7]
Example 4:優化
Input: root1 = [0,-10,10], root2 = [] Output: [-10,0,10]
Example 5:spa
Input: root1 = [1,null,8], root2 = [8,1] Output: [1,1,8,8]
Constraints:code
5000
nodes.[-10^5, 10^5]
.MEDIUM
題目內容很短,有兩個二叉搜索樹,須要把它們裏面的全部值放進一個數組中,而且結果是要保持順序遞增的。
讀完以後第一反應,這題還真是直白呀,沒包裝個什麼描述性的說法,搞的我都很差寫文章了,哼 >.<
關於什麼是二叉搜索樹,這個你們能夠自行搜索,固然我以後也會寫文章介紹常見的數據結構,一不當心給本身開了個新坑。
對於這道題目的要求,咱們能夠遍歷這兩個二叉搜索樹,獲得全部的值放進新數組中,而後再進行排序。固然,既然是很是科班的題目,天然有很套路的應對方式。畢竟一涉及到基於比較的排序,那複雜度就直接上 O(nlogn) 了。
咱們想要獲得符合遞增順序的二叉搜索樹內的全部值,直接進行中序遍歷便可,須要的時間複雜度是 O(n)。關於什麼是中序遍歷,一樣我會在新坑裏面提到。這裏先不作過多展開。
而後對於兩個有序數組進行合併,咱們能夠這樣作:
這樣咱們只須要 O(n) 的時間複雜度便可完成合並了。
固然在實際代碼中,咱們還能夠作一些優化,例如並不把數組開頭的值剔除掉,而是使用一個索引標識當前訪問的位置。由於對於數組這樣的線性表,咱們剃掉第一值也就意味着後續全部值的前移,代價仍是很大的。
const getAllElements = (root1, root2) => { const arr1 = []; const arr2 = []; traversal(root1, arr1); traversal(root2, arr2); const ret = []; let idx1 = idx2 = 0; while (idx1 < arr1.length && idx2 < arr2.length) { arr1[idx1] < arr2[idx2] ? ret.push(arr1[idx1++]) : ret.push(arr2[idx2++]); } while (idx1 < arr1.length) ret.push(arr1[idx1++]); while (idx2 < arr2.length) ret.push(arr2[idx2++]); return ret; function traversal(node, arr) { if (!node) return; traversal(node.left, arr); arr.push(node.val); traversal(node.right, arr); } };
上面的代碼跑到了 208ms,暫時 beats 100%。不過我跑完以後回頭一看,不得不說,寫的真醜。要是 code review 看到這樣的代碼,我確定是不會合並的。那咱們把它改的稍微好看一點吧。
const traversal = (node, arr = []) => { if (node) { traversal(node.left, arr); arr.push(node.val); traversal(node.right, arr); } return arr; }; const merge = (arr1, arr2) => { const ret = []; let idx1 = idx2 = 0; while (idx1 < arr1.length && idx2 < arr2.length) { arr1[idx1] < arr2[idx2] ? ret.push(arr1[idx1++]) : ret.push(arr2[idx2++]); } while (idx1 < arr1.length) ret.push(arr1[idx1++]); while (idx2 < arr2.length) ret.push(arr2[idx2++]); return ret; }; const getAllElements = (root1, root2) => merge(traversal(root1), traversal(root2));
這是一道比較套路的題,須要一點點科班知識,即二叉搜索樹和中序遍歷。相信你們應該很容易就能掌握這種套路了吧。
那麼最後加一個小思考,上面代碼中的 merge
方法是否能夠改成支持不定數量的數組合並呢,即 const merge = (...list) => {}
。但願小夥伴們能幫幫張小豬,麼麼嗒 >.<