def __init__(self):
        """
        Initialize your data structure here.
        """

        self.__stack_a = Deck()
        self.__stack_b = Deck()

        return
    def maxDepth__iterative__depth_first(self, root: TreeNode) -> int:
        """
        Solution to "maximum depth of binary tree" that...
        -   Uses iteration.
        -   Visits nodes in a depth-first order by using a stack.
        """

        from collections import deque as Deck

        #---------------------------------------

        max_depth = 0

        if not root:
            return max_depth

        stack = Deck([(root, 1)])

        while stack:

            (node, depth) = stack.pop()
            next_depth = depth + 1

            if node.left:
                stack.append((node.left, next_depth))

            if node.right:
                stack.append((node.right, next_depth))

            max_depth = max(max_depth, depth)

        return max_depth
        def is_same_tree(p: MaybeTreeNode, q: MaybeTreeNode) -> bool:
            """Tests `is_same_tree` iteratively, breadth-first."""

            queue = Deck([(p, q)])

            while queue:

                (p, q) = queue.popleft()

                # If both are empty trees, they are the same.
                if not p and not q:
                    continue

                # Now, if only one is empty, they are not the same.
                # If we got here, then we ruled out both being empty.
                if not p or not q:
                    return False

                # Now, both must be non-empty...

                # If their values are not equal, they are not the same. (Duh!)
                if p.val != q.val:
                    return False

                # Else, then append the left and right branches of `p` and `q` for testing.
                queue.append((p.left, q.left))
                queue.append((p.right, q.right))

            return True
Exemple #4
0
    def isValid__v1(self, s: str) -> bool:

        stack = Deck()  # -- records unmatched opening braces.

        # Move through all characters in string `s`:

        for c in s:

            # Try matching `c` to a brace.
            curr_brace = self.BRACES[c] if c in self.BRACES else None

            if curr_brace:

                curr_brace__id, curr_brace__part = curr_brace

                # We can always use an opening brace:

                if curr_brace__part == self.OPENING_PART:

                    stack.append(curr_brace)
                    continue

                # ... Now `curr_brace__part == self.CLOSING_PART` ...

                if stack:
                    # We must have a matching closing brace.
                    prev_brace = stack.pop()
                    prev_brace__id, prev_brace__part = prev_brace

                    if curr_brace__id == prev_brace__id:
                        # Note: We don't need to check `prev_brace__part`. It will always equal to `self.OPENING_PART`.

                        # `curr_brace` and `prev_brace` annihilate like matter and antimatter.
                        continue

                    else:
                        # We found an unmatched opening/closing brace 😢
                        return False

                else:
                    # We found an unmatchable closing brace 😢
                    return False

            # else:
            #     # `c` isn't a brace, so move on.
            #     continue

        # One last check...

        if stack:
            # We have unmatched opening braces 😭
            return False

        # We made it!
        return True
Exemple #5
0
        def tree_as_string(n: MaybeTreeNode) -> str:
            """Builds a string from `n` in BFT-LR order, iteratively."""

            queue = Deck([n])
            result = ""

            while queue:

                n = queue.popleft()

                if n is None:
                    result += " ~"

                else:
                    result += f" {n.val}"
                    queue.append(n.left)
                    queue.append(n.right)

            return result[1::]
Exemple #6
0
        def tree_as_string(n: MaybeTreeNode) -> str:
            """Builds a string from `n` in DFT-NLR order, iteratively."""

            stack = Deck([n])
            result = ""

            while stack:

                n = stack.pop()

                if n is None:
                    result += " ~"

                else:
                    result += f" {n.val}"
                    stack.append(n.right)
                    stack.append(n.left)

            return result[1::]
        def tree_as_string(n: MaybeTreeNode) -> str:
            """Builds a string from `n` in NLR order, iteratively."""

            stack = Deck([(n, 0)])
            result = ""

            while stack:

                (n, right_count) = stack.pop()
                # ⬆ We are tracking the number of "rights" we've taken so we can balance brackets.

                if n is None:
                    result += " ~" + ("]" * right_count)

                else:
                    result += f" [{n.val}"
                    stack.append((n.right, right_count + 1))
                    stack.append((n.left, 0))

            return result[1 ::]
Exemple #8
0
    def isSameTree__comparing_nodes__iterative__depth_first(
        self,
        p: TreeNode,
        q: TreeNode,
    ) -> bool:
        """
        Solution to "is same tree" that...
        -   Uses iteration.
        -   Performs a depth-first comparision of the trees by with a stack.
        """

        from collections import deque as Deck

        stack = Deck([(p, q)])

        while stack:

            (p, q) = stack.pop()

            # If both are empty trees, they are the same.
            if not p and not q:
                continue

            # Now, if only one is empty, they are not the same.
            # If we got here, then we ruled out both being empty.
            if not p or not q:
                return False

            # Now, both must be non-empty...

            # If their values are not equal, they are not the same. (Duh!)
            if p.val != q.val:
                return False

            # Else, then append the left and right branches of `p` and `q` for testing.
            stack.append((p.left, q.left))
            stack.append((p.right, q.right))

        return True
    def decodeString__match(self, encoded_string: str):
        """
        Match the most deeply nested part of the encoded string.
        """
        # @@ inspired by <https://stackoverflow.com/a/23561129/3281405>

        stack = Deck()

        for match in self.PATTERN.finditer(encoded_string):

            # -- we matched something! figure out what it is...

            groups = match.groupdict()
            brace = "opening" if groups["opening"] else "closing"
            index = match.start(brace)

            if encoded_string[index - 1] == r"\\":

                continue

            if brace == "opening":

                # -- we found the beginning of an encoded part
                # 1. process the current match into opening part
                # 2. push the opening part to the stack
                # 3. continue searching for matches

                count = int(groups["count"])
                count__start = match.start("count")
                embraced__start = index + len(self.OPENING_BRACE)

                stack.append((count, count__start, embraced__start))

                continue

            if brace == "closing":

                if stack:

                    # -- we found the ending of an encoded part
                    # 1. pop the last opening part from the stack
                    # 2. process the current match into the closing part
                    # 3. process the opening part and closing part into the decoded data
                    # 4. return the decoded part

                    (count, count__start, embraced__start) = stack.pop()

                    embraced__stop = index
                    embraced = encoded_string[embraced__start:embraced__stop]

                    decoded = (count, embraced)
                    decoded__start = count__start
                    decoded__stop = embraced__stop + len(self.CLOSING_BRACE)

                    return (decoded, decoded__start, decoded__stop)

                else:

                    print(
                        f"Missing the opening brace for the closing brace at {index}."
                    )

                    continue

        if len(stack) > 0:

            for (count, index) in stack:

                print(
                    f"Missing the closing brace for the opening brace at {index}."
                )

        return None
    def isSubtree__comparing_nodes__iterative__depth_first(
        self,
        s: TreeNode,
        t: TreeNode,
    ) -> TreeNode:
        """
        Solution to "subtree of another tree" that...
        -   Compares tree nodes.
        -   Uses iteration.
        -   Visits nodes in a depth-first order by using a queue.
        """

        from collections import deque as Deck

        def is_same_tree(p: MaybeTreeNode, q: MaybeTreeNode) -> bool:
            """Tests `is_same_tree` iteratively, depth-first."""

            stack = Deck([(p, q)])

            while stack:

                (p, q) = stack.pop()

                # If both are empty trees, they are the same.
                if not p and not q:
                    continue

                # Now, if only one is empty, they are not the same.
                # If we got here, then we ruled out both being empty.
                if not p or not q:
                    return False

                # Now, both must be non-empty...

                # If their values are not equal, they are not the same. (Duh!)
                if p.val != q.val:
                    return False

                # Else, then append the left and right branches of `p` and `q` for testing.
                stack.append((p.left, q.left))
                stack.append((p.right, q.right))

            return True

        #---------------------------------------

        stack = Deck([s])

        while stack:

            s = stack.pop()

            # Test if the local `s` and `t` are the same tree (`t` is a subtree of `s`).
            they_match = is_same_tree(s, t)

            # If we found a match, then return.
            if they_match:
                return True

            # Else, if there's more to the local `s`, then append the left and right branches of `s` for testing.
            elif s:
                stack.append(s.left)
                stack.append(s.right)

        return False