Last active
September 15, 2022 21:04
-
-
Save boraseoksoon/eb6beab76d76d3bb7b1cde4e0777b011 to your computer and use it in GitHub Desktop.
Invert binary in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; invert binary tree: https://leetcode.com/problems/invert-binary-tree/ | |
;; Given the root of a binary tree, invert the tree, and return its root. | |
;; Input: root = [4,2,7,1,3,6,9] | |
;; Output: [4,7,2,9,6,3,1] | |
;; Input: root = [2,1,3] | |
;; Output: [2,3,1] | |
;; Input: root = [] | |
;; Output: [] | |
;; Constraints: | |
;; The number of nodes in the tree is in the range [0, 100] . | |
;; -100 <= Node.val <= 100 | |
;; example: | |
;; when input is [4 2 7 1 3 6 9] | |
;; | |
;; 4 | |
;; 2 7 | |
;; 1 3 6 9 | |
;; output should be: [4 7 2 9 6 3 1] | |
;; | |
;; 4 | |
;; 7 2 | |
;; 9 6 3 1 | |
(def tree [4 2 7 1 3 6 9]) | |
(invert tree) ;; (4 7 2 9 6 3 1) | |
tree ;; [4 2 7 1 3 6 9] | |
(defn invert | |
[tree | |
& {:keys [level subtree last-index] | |
:or {level 1 subtree []}}] | |
(defn recur-split-half [vector] | |
(cond | |
(<= (count vector) 1) (apply list vector) | |
(= (count vector) 2) (apply list (reverse vector)) | |
:else | |
(let [half (or (split-at (/ (count vector) 2) vector) []) | |
first (or (nth half 0) []) | |
second (or (nth half 1) [])] | |
[(recur-split-half (vec second)) | |
(recur-split-half (vec first))]))) | |
(let | |
[log2 #(/ (Math/log %1) (Math/log 2)) | |
exponent #(Math/pow %1 %2) | |
power (Math/ceil (log2 (count tree))) | |
trailing-nil (take (exponent 2 power) (repeat nil)) | |
remove-trailing-nil #(reverse (drop-while nil? (reverse %1))) | |
tree (if (> level 1) | |
tree | |
(into tree trailing-nil))] | |
(cond | |
(not (vector? tree)) (throw (Error. "a tree must be a vector")) | |
(or (empty? tree) | |
(= (count tree) 1)) (apply list tree) | |
:else | |
(let [power (dec level) | |
from (or last-index 0) | |
to (+ from (exponent 2 power))] | |
(cond | |
(> to (count tree)) (recur-split-half subtree) | |
:else | |
(remove-trailing-nil | |
(flatten [(if (<= (count subtree) 1) | |
subtree | |
(recur-split-half subtree)) | |
(invert tree | |
:level (inc level) | |
:subtree (subvec tree from to) | |
:last-index to)]))))))) | |
(invert [4 2 7 1 3 6 9]) | |
;; (4 7 2 9 6 3 1) | |
(invert [1 2]) | |
;; (1 nil 2) | |
(invert [1 2 3 4]) | |
;; (1 3 2 nil nil nil 4) | |
(invert [4 2 7 1 3 6 9 11 33 66 99 111 333 666 999]) | |
;; (4 7 2 9 6 3 1 999 666 333 111 99 66 33 11) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Technically, it is different from the leet code requirement
where they require a mutable version of inverting binary tree
while this inverting binary tree attempts immutable version.