Created
August 2, 2017 19:39
-
-
Save jianminchen/1a09cc4b3c2607df137bf5e002f4bd4e to your computer and use it in GitHub Desktop.
Leetcode 301 - remove invalide paratheses - readable function name
This file contains 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
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace removeInvalidParatheses | |
{ | |
/// <summary> | |
/// Leetcode 301 - remove invalid paratheses | |
/// | |
/// </summary> | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
RunTestcase1(); | |
RunTestcase2(); | |
RunTestcase3(); | |
} | |
// test case 1: "()())()" -> ["()()()", "(())()"] | |
public static void RunTestcase1() | |
{ | |
var results = removeInvalidParentheses("()())()"); | |
} | |
// test case 2: "(a)())()" -> ["(a)()()", "(a())()"] | |
public static void RunTestcase2() | |
{ | |
var results = removeInvalidParentheses("(a)())()"); | |
} | |
// test case 3: ")(" -> [""] | |
public static void RunTestcase3() | |
{ | |
var results = removeInvalidParentheses(")("); | |
} | |
/// <summary> | |
/// code review on August 2, 2017 | |
/// </summary> | |
/// <param name="s"></param> | |
/// <returns></returns> | |
public static List<String> removeInvalidParentheses(String s) { | |
var invalid = countInvalidParatheses(s); | |
var maxRemovalLeft = invalid[0]; | |
var maxRemovalRight = invalid[1]; | |
var deDuplicate = new HashSet<string>(); | |
FindAllValidCandidates(s, 0, deDuplicate, new StringBuilder(), maxRemovalLeft, maxRemovalRight, 0); | |
return new List<String>(deDuplicate); | |
} | |
/// <summary> | |
/// count how many invalid open and close paratheses | |
/// by scanning the string from left to right once | |
/// </summary> | |
/// <param name="s"></param> | |
/// <returns></returns> | |
private static int[] countInvalidParatheses(string s) | |
{ | |
var maxRemovalLeft = 0; | |
var maxRemovalRight = 0; | |
var length = s.Length; | |
// preprocess the string to get maximum number of | |
// invalid left and right paratheses | |
for (int i = 0; i < length; i++) | |
{ | |
var visit = s[i]; | |
bool isOpen = visit == '('; | |
bool isClose = visit == ')'; | |
if (isOpen) | |
{ | |
maxRemovalLeft++; | |
} | |
else if (isClose) | |
{ | |
if (maxRemovalLeft != 0) | |
{ | |
maxRemovalLeft--; | |
} | |
else | |
{ | |
maxRemovalRight++; | |
} | |
} | |
} | |
return new int[] { maxRemovalLeft, maxRemovalRight }; | |
} | |
/// <summary> | |
/// code review on August 2, 2017 | |
/// this algorithm will do brute force | |
/// DFS search, 2^n choice. | |
/// argument: matchChecking | |
/// make sure that the parathese is correct to match | |
/// "()", | |
/// if "(" is used, then matchChecking should increment one first | |
/// and then visit ")", | |
/// if ")" is used, then decrement one and then is equal to zero. | |
/// ")(", | |
/// if ")" is used, then matchChecking decrease one for ")", < 0, return false | |
/// | |
/// Find all valid candidates, remove minimum invalid paratheses. | |
/// Using StringBuilder to set the length, the backtracking is very easy to write. | |
/// </summary> | |
/// <param name="s"></param> | |
/// <param name="index"></param> | |
/// <param name="deDuplicate"></param> | |
/// <param name="candidate"></param> | |
/// <param name="maxRemovalLeft"></param> | |
/// <param name="maxRemovalRight"></param> | |
/// <param name="matchChecking"></param> | |
public static void FindAllValidCandidates( | |
String s, | |
int index, | |
HashSet<String> deDuplicate, | |
StringBuilder candidate, | |
int maxRemovalLeft, | |
int maxRemovalRight, | |
int matchChecking) | |
{ | |
if (maxRemovalLeft < 0 || maxRemovalRight < 0 || matchChecking < 0) | |
{ | |
return; | |
} | |
int length = s.Length; | |
bool finishScan = index == length; | |
// base case | |
if (finishScan) | |
{ | |
if (maxRemovalLeft == 0 && maxRemovalRight == 0 && matchChecking == 0) | |
{ | |
deDuplicate.Add(candidate.ToString()); | |
} | |
return; | |
} | |
var visit = s[index]; | |
var current = candidate.Length; | |
bool isOpen = visit == '('; | |
bool isClose = visit == ')'; | |
if (isOpen) | |
{ | |
// not use (, remove '(' | |
FindAllValidCandidates(s, index + 1, deDuplicate, candidate, maxRemovalLeft - 1, maxRemovalRight, matchChecking); | |
// use ( | |
FindAllValidCandidates(s, index + 1, deDuplicate, candidate.Append(visit), maxRemovalLeft, maxRemovalRight, matchChecking + 1); | |
} | |
else if (isClose) | |
{ | |
// not use ) | |
FindAllValidCandidates(s, index + 1, deDuplicate, candidate, maxRemovalLeft, maxRemovalRight - 1, matchChecking); | |
// use ) | |
FindAllValidCandidates(s, index + 1, deDuplicate, candidate.Append(visit), maxRemovalLeft, maxRemovalRight, matchChecking - 1); | |
} | |
else | |
{ | |
FindAllValidCandidates(s, index + 1, deDuplicate, candidate.Append(visit), maxRemovalLeft, maxRemovalRight, matchChecking); | |
} | |
// backtracking - remove the last char | |
candidate.Length = current; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment