a few solutions
Perform a linear scan of the input string s and use a stack S to store each the index of each \'(\' character.  Whenever a \')\' character is seen, pop the inde
Perform a linear scan of the input string `s` and use a stack `S` to store each the index of each `\'(\'` character.  Whenever a `\')\'` character is seen, pop the index of the nearest corresponding match (if possible), otherwise if the stack is empty, then mark the current index to be deleted, ie. we add the index onto the set `X`.  Upon completion of the linear scan, we append "leftover" indices of the stack `S` onto `X` to be deleted.\n\nIn summary:\n\n1. we mark indices of `\')\'` to be deleted **during** the linear scan of the input string `s`\n2. we mark indices of `\'(\'` to be deleted **after** the linear scan of the input string `s`\n\n---\n\n*Kotlin*\n```\nclass Solution {\n    fun minRemoveToMakeValid(s: String): String {\n        var X = mutableSetOf<Int>()\n        var S = mutableListOf<Int>()\n        for ((i, c) in s.toCharArray().withIndex()) {\n            if (c == \'(\')\n                S.add(i)\n            if (c == \')\') {\n                if (0 < S.size)\n                    S.removeAt(S.lastIndex)\n                else\n                    X.add(i)\n            }\n        }\n        for (i in S) X.add(i)\n        return s.toCharArray().withIndex().filter{ (i, c) -> !X.contains(i) }.map{ (_, c) -> c }.joinToString("")\n    }\n}\n```\n\n*Javascript*\n```\nlet minRemoveToMakeValid = (s, S = [], X = new Set()) => {\n    for (let i = 0; i < s.length; ++i) {\n        let c = s[i];\n        if (c == \'(\')\n            S.push(i);\n        if (c == \')\') {\n            if (S.length)\n                S.pop();\n            else\n                X.add(i);\n        }\n    }\n    S.forEach(i => X.add(i));\n    return s.split(\'\').filter((_, i) => !X.has(i)).join(\'\');\n};\n```\n\n*Python3*\n```\nclass Solution:\n    def minRemoveToMakeValid(self, s: str, cnt = 0) -> str:\n        S = []\n        X = set()\n        for i, c in enumerate(s):\n            if c == \'(\':\n                S.append(i)\n            if c == \')\':\n                if len(S):\n                    S.pop()\n                else:\n                    X.add(i)\n        [X.add(i) for i in S]\n        return \'\'.join(c for i, c in enumerate(s) if i not in X)\n```\n\n*Rust*\n```\nuse std::collections::HashSet;\nimpl Solution {\n    pub fn min_remove_to_make_valid(s: String) -> String {\n        let mut S = vec![];\n        let mut R = HashSet::new();\n        for (i, c) in s.chars().enumerate() {\n            if c == \'(\' {\n                S.push(i);\n            }\n            if c == \')\' {\n                if 0 < S.len() {\n                    S.pop();\n                } else {\n                    R.insert(i);\n                }\n            }\n        }\n        let L: HashSet<usize> = S.drain(..).collect();\n        return s.chars().enumerate().filter(|(i, c)| !L.contains(i) && !R.contains(i)).map(|(i, c)| c).collect();\n    }\n}\n```\n\n*C++*\n```\nclass Solution {\npublic:\n    using Set = unordered_set<int>;\n    using VI = vector<int>;\n    string minRemoveToMakeValid(string s, string t = {}, VI S = {}, Set X = {}) {\n        for (auto i{ 0 }; i < s.size(); ++i) {\n            auto c = s[i];\n            if (c == \'(\')\n                S.push_back(i);\n            if (c == \')\') {\n                if (S.size())\n                    S.pop_back();\n                else\n                    X.insert(i);\n            }\n        }\n        X.insert(S.begin(), S.end());\n        copy_if(s.begin(), s.end(), back_inserter(t), [&X, i = -1](auto c) mutable { return X.find(++i) == X.end(); });\n        return t;\n    }\n};\n```\n\n---\n\n**Legacy Solutions November 4, 2019:**\nLet ```t``` be ```s``` transformed with minimum parens removed to make a valid paren string.  ```t``` is generated by iterating over each index ```i``` of ```s```:\n* **Case 1:** if ```s[i]``` is ```(```, then push index ```i``` onto the stack since ```s[i]``` contains a potentially a "leftover" ```(```\n* **Case 2:** if ```s[i]``` is ```)```, then the next step depends on the current stack state:\n\t* **either** the stack is empty and the ```)``` is superfluous and it\'s index ```i``` is immediately marked for deletion\n\t* **or** the stack contains a matching ```(``` and it\'s index ```i``` is popped off the stack [ie. the last seen ```(``` matches the current ```)```, thus the last seen ```(``` is *not* a potential "leftover"]\n* **Case 3:** if ```s[i]``` is an alpha char, then no additional processing is needed [ie. it will be copied from ```s``` to ```t``` "as is"]\n\n**Notes:**\n* For *case 1*, we do *not* know if each potential "leftover" ```(``` is actual "leftover" until ```s``` is completely processed since each potential future corresponding ```)``` found causes the index ```i``` associated with each potential "leftover" ```(``` to be popped off the stack.\n* After ```s``` is completely processed all indices remaining in the stack are associated with "leftover" ```(```.  Mark all these indices for deletion.\n\n*Javascript*\n```\nvar minRemoveToMakeValid = (s, t=[], del=new Set(), stack=[]) => {\n    for (let i=0; i < s.length; ++i) {\n        if (s[i] == \'(\')\n            stack.push(i);\n        if (s[i] == \')\') {\n            if (stack.length == 0)\n                del.add(i);\n            else\n                stack.pop();\n        }\n    }\n    stack.forEach(i => del.add(i));\n    for (let i=0; i < s.length; ++i)\n        if (!del.has(i))\n            t.push(s[i]);\n    return t.join(\'\');\n};\n```\n\n*C++*\n```\nclass Solution {\npublic:\n    string minRemoveToMakeValid(string s, string t={}, unordered_set<int> del={}, vector<int> stack={}) {\n        for (auto i=0; i < s.size(); ++i) {\n            if (s[i] == \'(\')\n                stack.push_back(i);\n            if (s[i] == \')\') {\n                if (stack.empty())\n                    del.insert(i);\n                else\n                    stack.pop_back();\n            }\n        }\n        del.insert(stack.begin(), stack.end());\n        for (auto i=0; i < s.size(); ++i)\n            if (del.find(i) == del.end())\n                t.push_back(s[i]);\n        return t;\n    }\n};\n```
[]