class Solution:
    def removeInvalidParentheses(self, s: str) -> List[str]:
        """tc O(2^N)   sc O(N)
        return all results => backtracking? (maintain current path valid)  + with minimun removal =how to determine valid? ==>  
        
        main idea:  generate unique answer exactly once (no rely on set)
                    to find out last removal position, we need to keep tracking last removal position and only remove ) 
                    for extra open parenthesis, (() ((), do same right -> left 
        """
        self.res = []
        
    #open_close :  ('(',')')
    """
    @last_open_i: position to start count 
    @last_close_j: position to start removing, remove position j range is [last_close_j,i] inclusive  
    
    """
        def remove(s,last_open_i,last_close_j,open,close): 
            cnt = 0
            for i in range(last_open_i,len(s)):
                if s[i] == open:
                    cnt += 1
                if s[i]== close:
                    cnt -= 1
                if cnt >= 0:
                    continue
                # cnt < 0 chose start pos to remove duplicate `close` 
                # stragtegy to avoid repeated removal is only remove 
                for j in range(last_close_j,i+1):
                    if s[j] == close and (j== last_close_j or s[j-1] != close):
                        #(1) new_string = s[:j]+s[j+1:]
                        #(2) last_open_i: next position to scan open should be i+1 in s but since we removed s[j] new open position of open to start should be i  
                        #(3) last_close_j is j, same logic as (2), hence we get j 
                        remove(s[:j]+s[j+1:len(s)],i,j,open,close)
                return #!!! important: because after recursively removing invalid close parenthesis, we should not  continue any more because inner recursion has taken care of it 
            # assumiing for i loop there is no invalid parathesis. otherwise, we will not reach here since there is `return`
            rev = s[::-1]
            if open == '(': # left -> right end 
                remove(rev,0,0,')','(')  # here can replace with close,open but can't replace with  last_close_j,last_open_i
            else:
                self.res.append(rev) # finished right -> left 
        remove(s,0,0,'(',')') 
        return self.res