Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3d59475

Browse files
check in source code
1 parent 497d30c commit 3d59475

File tree

2 files changed

+300
-0
lines changed

2 files changed

+300
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace Leetcode301_removeInvalidParentheses
9+
{
10+
class Program
11+
{
12+
/// <summary>
13+
/// Leetcode 301: remove invalid parentheses
14+
/// July 19, 2018
15+
/// Study Leetcode discussion:
16+
/// https://leetcode.com/problems/remove-invalid-parentheses/discuss/75027/Easy-Short-Concise-and-Fast-Java-DFS-3-ms-solution
17+
///
18+
/// Highlights of design:
19+
/// 1. Use recursive function
20+
/// 2. Find first unmatched ), and then remove all possible ) from the beginning;
21+
/// make recursive call;
22+
/// 3. After the unmatched close brackets has been removed, and then continue to
23+
/// process unmatched open brackets. Just call the reversed array.
24+
/// 4. At the end of the recursive function, only when the reversed string is processed,
25+
/// add the string to the valid string list;
26+
/// 5. Use two pointers left and right to scan through the string, find first char in every
27+
/// consecutive unmatched paretheses, add the option to remove it once.
28+
/// this is a nice and smart tip to remember, code from line 75 to 83.
29+
/// </summary>
30+
/// <param name="args"></param>
31+
static void Main(string[] args)
32+
{
33+
RunTestcase();
34+
}
35+
36+
static void RunTestcase()
37+
{
38+
var validStrings = RemoveInvalidParentheses("()())()");
39+
40+
Debug.Assert(validStrings[0].CompareTo("()()()") == 0 ||
41+
validStrings[0].CompareTo("(())()") == 0);
42+
}
43+
44+
/// <summary>
45+
///
46+
/// </summary>
47+
/// <param name="source"></param>
48+
/// <returns></returns>
49+
public static List<String> RemoveInvalidParentheses(String source)
50+
{
51+
var validStrings = new List<String>();
52+
53+
var leftIndex = 0;
54+
var rightIndex = 0;
55+
var defaultLeftToRight = new char[] { '(', ')' };
56+
57+
removeInvalidCloseParenthesesTwoScans(source, validStrings, leftIndex, rightIndex, defaultLeftToRight);
58+
return validStrings;
59+
}
60+
61+
/// <summary>
62+
/// code review July 19, 2018
63+
/// remove invalid close parentheses two scans,
64+
/// one is from left to right and the second one is from right to left.
65+
///
66+
/// go through the test case to figure out:
67+
/// "()())()"
68+
/// write a story how to find valid strings:
69+
/// 1. First remove extra close one.
70+
/// Find the first one unmatched close one, and then use two pointers
71+
/// to go over all possible places to remove close one. Remove close one.
72+
/// for example, ()())(), iterate the string from left to right, find index = 4,
73+
/// ) close parenthese is the extra one. What I like to do is to scan left to right
74+
/// to find all possible ), and then remove it.
75+
/// To make time complexity to linear, we can save close one index to a data structure, like a list.
76+
/// In case there are hundreds of chars, but only two or three close parentheses.
77+
///
78+
///
79+
/// Time complexity:
80+
/// Think about how many possible valid strings first.
81+
/// define close parentheses at most - M
82+
/// define open parentheses at most - N
83+
/// define unmatched close parentheses at most - M1
84+
/// define unmatched open paretnthese at most - N1
85+
/// possible choices: M ^ M1 * N ^N1
86+
/// </summary>
87+
/// <param name="s"></param>
88+
/// <param name="validStrings"></param>
89+
/// <param name="right"></param>
90+
/// <param name="left"></param>
91+
/// <param name="parentheses"></param>
92+
private static void removeInvalidCloseParenthesesTwoScans(
93+
String s,
94+
List<String> validStrings,
95+
int right,
96+
int left,
97+
char[] parentheses)
98+
{
99+
var openOne = parentheses[0];
100+
var closeOne = parentheses[1];
101+
102+
for (int openCount = 0, rightIndex = right; rightIndex < s.Length; ++rightIndex)
103+
{
104+
var current = s[rightIndex];
105+
if (current == openOne)
106+
{
107+
openCount++;
108+
}
109+
110+
if (current == closeOne)
111+
{
112+
openCount--;
113+
}
114+
115+
if (openCount >= 0)
116+
{
117+
continue;
118+
}
119+
120+
// find first unmatched parenthese, and then go over all the options to remove it.
121+
// for test case ()())(), close one has two positions, one is index = 1, index = 3 or 4
122+
// remove index = 1, and index 3 and 4, only remove first one. Since the second one will be the same
123+
for (int leftIndex = left; leftIndex <= rightIndex; ++leftIndex)
124+
{
125+
if ( s[leftIndex] == closeOne &&
126+
( leftIndex == left || s[leftIndex - 1] != closeOne))
127+
{
128+
// remove extra close one
129+
var stringFiltered = s.Substring(0, leftIndex) + s.Substring(leftIndex + 1);
130+
removeInvalidCloseParenthesesTwoScans(stringFiltered, validStrings, rightIndex, leftIndex, parentheses);
131+
}
132+
}
133+
134+
return;
135+
}
136+
137+
138+
var reversed = new String(s.ToCharArray().Reverse().ToArray());
139+
140+
if (parentheses[0] == '(') // finished left to right
141+
{
142+
removeInvalidCloseParenthesesTwoScans(reversed, validStrings, 0, 0, new char[] { ')', '(' });
143+
}
144+
else // finished right to left
145+
{
146+
validStrings.Add(reversed);
147+
}
148+
}
149+
}
150+
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace Leetcode301_removeInvalidParentheses
9+
{
10+
class Program
11+
{
12+
/// <summary>
13+
/// Leetcode 301: remove invalid parentheses
14+
/// July 19, 2018
15+
/// Study Leetcode discussion:
16+
/// https://leetcode.com/problems/remove-invalid-parentheses/discuss/75027/Easy-Short-Concise-and-Fast-Java-DFS-3-ms-solution
17+
///
18+
/// Highlights of design:
19+
/// 1. Use recursive function
20+
/// 2. Find first unmatched ), and then remove all possible ) from the beginning;
21+
/// make recursive call;
22+
/// 3. After the unmatched close brackets has been removed, and then continue to
23+
/// process unmatched open brackets. Just call the reversed array.
24+
/// 4. At the end of the recursive function, only when the reversed string is processed,
25+
/// add the string to the valid string list;
26+
/// 5. Use two pointers left and right to scan through the string, find first char in every
27+
/// consecutive unmatched paretheses, add the option to remove it once.
28+
/// this is a nice and smart tip to remember, code from line 75 to 83.
29+
/// </summary>
30+
/// <param name="args"></param>
31+
static void Main(string[] args)
32+
{
33+
RunTestcase();
34+
}
35+
36+
static void RunTestcase()
37+
{
38+
var validStrings = RemoveInvalidParentheses("()())()");
39+
40+
Debug.Assert(validStrings[0].CompareTo("()()()") == 0 ||
41+
validStrings[0].CompareTo("(())()") == 0);
42+
}
43+
44+
/// <summary>
45+
///
46+
/// </summary>
47+
/// <param name="source"></param>
48+
/// <returns></returns>
49+
public static List<String> RemoveInvalidParentheses(String source)
50+
{
51+
var validStrings = new List<String>();
52+
53+
var leftIndex = 0;
54+
var rightIndex = 0;
55+
var defaultLeftToRight = new char[] { '(', ')' };
56+
57+
removeInvalidCloseParenthesesTwoScans(source, validStrings, leftIndex, rightIndex, defaultLeftToRight);
58+
return validStrings;
59+
}
60+
61+
/// <summary>
62+
/// code review July 19, 2018
63+
/// remove invalid close parentheses two scans,
64+
/// one is from left to right and the second one is from right to left.
65+
///
66+
/// go through the test case to figure out:
67+
/// "()())()"
68+
/// write a story how to find valid strings:
69+
/// 1. First remove extra close one.
70+
/// Find the first one unmatched close one, and then use two pointers
71+
/// to go over all possible places to remove close one. Remove close one.
72+
/// for example, ()())(), iterate the string from left to right, find index = 4,
73+
/// ) close parenthese is the extra one. What I like to do is to scan left to right
74+
/// to find all possible ), and then remove it.
75+
/// To make time complexity to linear, we can save close one index to a data structure, like a list.
76+
/// In case there are hundreds of chars, but only two or three close parentheses.
77+
///
78+
///
79+
/// Time complexity:
80+
/// Think about how many possible valid strings first.
81+
/// define close parentheses at most - M
82+
/// define open parentheses at most - N
83+
/// define unmatched close parentheses at most - M1
84+
/// define unmatched open paretnthese at most - N1
85+
/// possible choices: M ^ M1 * N ^N1
86+
/// </summary>
87+
/// <param name="s"></param>
88+
/// <param name="validStrings"></param>
89+
/// <param name="right"></param>
90+
/// <param name="left"></param>
91+
/// <param name="parentheses"></param>
92+
private static void removeInvalidCloseParenthesesTwoScans(
93+
String s,
94+
List<String> validStrings,
95+
int right,
96+
int left,
97+
char[] parentheses)
98+
{
99+
var openOne = parentheses[0];
100+
var closeOne = parentheses[1];
101+
102+
for (int openCount = 0, rightIndex = right; rightIndex < s.Length; ++rightIndex)
103+
{
104+
var current = s[rightIndex];
105+
if (current == openOne)
106+
{
107+
openCount++;
108+
}
109+
110+
if (current == closeOne)
111+
{
112+
openCount--;
113+
}
114+
115+
if (openCount >= 0)
116+
{
117+
continue;
118+
}
119+
120+
// find first unmatched parenthese, and then go over all the options to remove it.
121+
// for test case ()())(), close one has two positions, one is index = 1, index = 3 or 4
122+
// remove index = 1, and index 3 and 4, only remove first one. Since the second one will be the same
123+
for (int leftIndex = left; leftIndex <= rightIndex; ++leftIndex)
124+
{
125+
if ( s[leftIndex] == closeOne &&
126+
( leftIndex == left || s[leftIndex - 1] != closeOne))
127+
{
128+
// remove extra close one
129+
var stringFiltered = s.Substring(0, leftIndex) + s.Substring(leftIndex + 1);
130+
removeInvalidCloseParenthesesTwoScans(stringFiltered, validStrings, rightIndex, leftIndex, parentheses);
131+
}
132+
}
133+
134+
return;
135+
}
136+
137+
138+
var reversed = new String(s.ToCharArray().Reverse().ToArray());
139+
140+
if (parentheses[0] == '(') // finished left to right
141+
{
142+
removeInvalidCloseParenthesesTwoScans(reversed, validStrings, 0, 0, new char[] { ')', '(' });
143+
}
144+
else // finished right to left
145+
{
146+
validStrings.Add(reversed);
147+
}
148+
}
149+
}
150+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /