def valid_parenthesis(s: str) -> bool:
    """
    Returns whether the parenthetical expression, s, is valid.
    @Algorithm: - Keep track of open parens that require terminating using a stack
                - If we encounter an open paren, push to indicate we are still to find a terminating closed paren
                - If we encounter a closed paren,
                    - If open paren stack is empty, then we cannot match the closed paren to anything -- invalid
                    - Check if closed paren terminates the open paren at the top of the stack
                        - If it does, pop() the open paren to indicate we have found its termination
                        - If it doesn't, then -- invalid
    :param s: string with parentheses
    :Time: O(N)
    :Space: O(N)
    :return: true if valid
    """
    open_parens = Stack(
    )  # tracks history of open parentheses that need to be terminated
    for c in s:
        if c in closed_parens:  # if closed paren, check if top of stack is open paren of same type
            if open_parens.get_size() == 0:
                return False  # no open paren to match this closed paren

            if open_parens.peek() == matching_open_paren[
                    c]:  # proper termination found for open paren at top of stack
                open_parens.pop(
                )  # pop to indicate this paren has found a terminating closing paren
            else:
                return False  # incorrect termination
        else:
            open_parens.push(c)  # if open paren, add to stack

    return open_parens.is_empty(
    )  # if stack is empty, valid; else, indicates an open paren hasn't been terminated
class MyQueue(Queue):
    def __init__(self):
        super(MyQueue, self).__init__()
        self.s1 = Stack()
        self.s2 = Stack()

    def enqueue(self, item):
        """
        Enqueues an item onto the queue by pushing the item onto stack 1.
        :param item: item to enqueue
        :Time: O(1)
        :Space: O(1)
        :return: none
        """
        self.s1.push(item)  # Simply push item onto s1

    def dequeue(self):
        """
        Returns the element at the front of the queue. This is achieved by popping from s2, which mimics a queue.
        @note: To save needlessly shifting elements into s2, we will only populate s2 when it is depleted.
                I.e. only update s2 until the previously populated items have been popped.
        :Time: O(N)
        :Space: O(N)
        :return: none
        """
        if self.s2.is_empty(
        ):  # We will only update s2 when it cannot be popped() from further
            self.shift_stacks()
        return self.s2.pop()

    def peek(self):
        if self.s2.is_empty():
            self.shift_stacks()
        return self.s2.peek()

    def shift_stacks(self):
        """
        Pops each element in s1 and pushes it onto s2 such that s2 now mimics a queue which can be dequeued via popping
        :Time: O(N)
        :Space: O(N)
        :return: none
        """
        while not self.s1.is_empty():  # pop() from s1 and push() onto s2
            self.s2.push(self.s1.pop())

    def get_size(self):
        return self.s1.get_size() + self.s2.get_size(
        )  # Size of queue is the size of both stacks

    def is_empty(self):
        return self.get_size() == 0
Example #3
0
def runStack():
    s = Stack()

    print(s.isEmpty())
    s.push(4)
    s.push('dog')
    print(s.peek())
    s.push(True)
    print(s.size())
    print(s.isEmpty())
    s.push(8.4)
    print(s.pop())
    print(s.pop())
    print(s.size())
Example #4
0
def runStack():
    s=Stack()

    print(s.isEmpty())
    s.push(4)
    s.push('dog')
    print(s.peek())
    s.push(True)
    print(s.size())
    print(s.isEmpty())
    s.push(8.4)
    print(s.pop())
    print(s.pop())
    print(s.size())