针对这两道前后关联的题,在这里给出自己的解法。
首先说20题,括号匹配问题。
对于括号匹配问题,相信大家都学数据结构应该都学过,使用栈来存储待匹配的括号。在此,为了省事,我没有直接使用STL的内容,而是突发奇想,使用数组来自己实现栈的功能。考虑到对给定的字符串,我们只需维护一个有先后顺序的字符序列来表示当前最需要进行匹配的字符是哪个,就如同使用栈的先进后出特性。我们使用一个数组array来维护此先后顺序。对于数组第i个元素的值A[i],表示字符串中如果第i个字符成功匹配后下一个需要被匹配字符的位置。使用top变量来记录当前需要匹配哪个字符,当top位置元素匹配成功后,更新top = A【top】,就如同弹出栈顶元素,整个A数组就如同逆序链表,可以直接访问前一个元素(弹栈后的元素),每次添加删除元素都在尾部(栈顶)。
初始数组每个元素为-1(在做这道题时就是随便设置了一个不干扰正常字符位置的数字,做32题时才发现设置成-1用处还是很大的)。
下面给个例子:
对于字符串:
( ( )( ) )
0 1 2 3 4 5
S[i]为字符串第i个字符。
1、第一步 top=0;A[0]=-1;
2、第二步 S[1]与S【top】不匹配,更新A【1】=0;top = 1;
3、 第三步 S【2】与S【top=1】匹配,top = A【top=1】=0,A【1】=-1;
4、第四步 S【3】与S【top=0】不匹配,更新A【3】=0;top=3
5、第五步S【4】与S【top=3】匹配,更新top=A【top=3】=0,A【3】=-1;
6、第六部 S【5】与S【top=0】匹配,更新top=A【top=0】=-1;
按照字符串长度循环结束。
最后top=-1,代表全部括号匹配成功。
O(n) O(n)的算法
代码如下:
class Solution {
public:
bool isValid(string s) {
/*array arr[i] = index, the index is the previous characters's index at s,and will have a variable name top represents the current
* characters which need to pregex,we can think the arr is a ourself's stack, and the top is the stack's element at the top.
*/
int len = s.length();
if( len == 1 )
return false;
int *arr = new int[len],top = -1,t,flag;
memset(arr,-1,len*sizeof(int));
for( int i=0; i<len; i++ )
{
if( top == -1 )
{
top = i;
continue;
}
flag = s[i] - s[top];
if( flag<=2 && flag>=-2 && flag != 0 )
{
t = top;
top = arr[top];
arr[t] = -1;
}
else
{
arr[i] = top;
top = i;
}
}
if( top == -1 )
return true;
else
return false;
}
};
对于32题,首先想到dp,使用区间(i.j)作为子问题。
需要O(n),O(n*n)的复杂度,第二个为空间复杂度。
对此没做多想,感觉没啥意思,O(n*n)的空间复杂度有些不能接受。
于是联系第20题,当top处的括号匹配成功时代表此时有一个新的合法括号序列,在此时更新最大长度max即可。
而新合法括号序列长度即为A【top】到循环变量i的长度。(考虑边界情况,当top=0时,将A【0】设置为-1,正好与其他情况统一了,否则对A【top】需分情况讨论)
O(n),O(n)的复杂度,可以接受了。
下面给出代码:
class Solution {
public:
int longestValidParentheses(string s) {
int len = s.length();
if( len <= 1 )
return 0;
int *arr = new int[len],top = -1,t,flag;
int maxlen = 0;
memset(arr,-1,len*sizeof(int));
for( int i=0; i<len; i++ )
{
if( top == -1 )
{
top = i;
continue;
}
flag = s[i] - s[top];
if( flag==1 )
{
t = top;
top = arr[top];
arr[t] = -1;
maxlen = maxlen < (i-top) ? (i-top) : maxlen;
}
else
{
arr[i] = top;
top = i;
}
}
return maxlen;
}
};
运行时间为10ms,不知道他们9ms是怎么做的,难道是有logn的算法?还是我的程序效率不行?求人解答。