-
输入
- 第一行输入一个数N(0<N<=100),表示有N组测试数据。后面的N行输入多组输入数据,每组输入数据都是一个字符串S(S的长度小于10000,且S不是空串),测试数据组数少于5组。数据保证S中只含有"[","]","(",")"四种字符 输出
每组输入数据的输出占一行,如果该字符串中所含的括号是配对的,则输出Yes,如果不配对则输出No
我的答案:
01.
#include <iostream>
02.
#include <string>
03.
#include <list>
04.
using
namespace
std;
05.
06.
07.
bool
ifMatch(
char
a,
char
b){
08.
switch
(a){
09.
case
'('
:
if
(b ==
')'
)
return
true
;
10.
break
;
11.
12.
case
'['
:
if
(b ==
']'
)
return
true
;
13.
break
;
14.
15.
default
:
break
;
16.
}
17.
return
false
;
18.
}
19.
20.
bool
removeMatch(string text){
21.
string newText;
22.
bool
iftext =
false
;
23.
if
(text.size() == 0 )
24.
return
true
;
25.
for
(
int
i =0 ; i<text.size() ; )
26.
{
27.
28.
29.
if
(i!=(text.size()-1)){
30.
if
(ifMatch(text.at(i),text.at(i+1)))
31.
{
32.
33.
i = i+2;
34.
iftext =
true
;
35.
}
36.
else
{
37.
newText.push_back(text.at(i));
38.
i++;
39.
}
40.
}
41.
else
{
42.
newText.push_back(text.at(i));
43.
i++;
44.
}
45.
46.
}
47.
if
(iftext)
48.
return
removeMatch(newText);
49.
else
50.
return
false
;
51.
}
52.
53.
54.
bool
ifAllMatch(string text){
55.
int
numberofchars = text.length();
56.
for
(
int
i =0 ;i<numberofchars;i++)
57.
{
58.
if
(text.at(i)==
'('
||text.at(i)==
')'
||text.at(i)==
'['
||text.at(i)==
']'
)
59.
continue
;
60.
else
61.
{
62.
cout<<
"text contains unvalid chars"
<<endl;
63.
return
false
;
64.
}
65.
}
66.
67.
return
removeMatch(text);
68.
}
69.
70.
71.
int
main(){
72.
73.
int
n;
74.
cin>>n;
75.
list<string> strs;
76.
for
(
int
i = 0 ;i<n;i++){
77.
string str;
78.
cin>>str;
79.
strs.push_back(str);
80.
}
81.
for
(
int
i = 0 ;i<n;i++){
82.
if
(ifAllMatch(strs.front()))
83.
cout<<
"Yes"
<<endl;
84.
else
85.
cout<<
"No"
<<endl;
86.
strs.pop_front();
87.
}
88.
89.
return
0;
90.
}
标准答案:
01.
#include<iostream>
02.
#include<vector>
03.
#include<string>
04.
using
namespace
std;
05.
int
main()
06.
{
07.
int
n;
08.
cin>>n;
09.
while
(n--)
10.
{
11.
vector<
char
> vec;
12.
string ch;
13.
vec.push_back(
' '
);
14.
cin>>ch;
15.
for
(
int
i=0;i<ch.length();i++)
16.
{
17.
vec.push_back(ch[i]);
18.
if
( vec.back()-1 == *(vec.end()-2) || vec.back()-2 == *(vec.end()-2))
19.
{
20.
vec.pop_back();
21.
vec.pop_back();
22.
}
23.
}
24.
if
(vec.size()==1)
25.
cout<<
"Yes"
<<endl;
26.
else
27.
cout<<
"No"
<<endl;
28.
}
29.
return
0;
30.
}
诚然,我写的程序耗时很久并且占内存较大,耗时较长,是个比较粗糙的算法。然而归结起来是以下两点原因:
1:对ASCII码的不熟悉,可以归结为对计算机语言原理的不熟悉和运用不纯熟。
2:对c++的std原生库的理解与运用不到位,可以归结为对C++的理解不够深刻。
一:ASCII码的运用
在本题目中涉及到ASCII码的是 [ 、] 、( 、) 四个字符。而在ASCII码中,(为40,)为41,[为91,]为93。所以在标准答案中,如果两个字符相减为1,或为2则判断出一对match的括号。由于限制了字符的输入,当然也只有这四种字符输入,不会有其它影响。然而我在我写的程序里没使用到ASCII码,而是写了一个函数通过字符对应去判断是否match,而且增加了对输入字符的限制,也使得我的程序耗时与内存消耗更大。
而在判断其它时,又该如何巧妙运用ASCII码呢?
三种情况下可以很好地用上ASCII码:当字符中只包含了,0-9,A-Z,a-z时可以运用上:
0-9对应的ASCII码为48-57,A-Z对应的ASCII码为65-90,a-z对应的ASCII码为97-122.
如判断两个字符是否对应的大小写英文字母 如A和a,只需要判断 条件 |A-a|==32即可。其它情况自由发挥。
二:std::vector与std::list的运用
标准答案采取的方法是,输入字符串逐个以栈的方式压入vector中,每次压入之后比较倒数第二和第一的字符,如果是匹配的括号,则两个字符都出栈,否则继续添加下一个字符进堆栈里,直到最后一个字符,然后判断vector的长度,从而判断是否所有的括号都匹配到了。
vector与list的区别:
vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随机存取(即使用[]操作符访问其中的元素),但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝(复杂度是O(n)),另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。
list是由数据结构中的双向链表实现的,因此它的内存空间可以是不连续的。因此只能通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率,需要遍历中间的元素,搜索复杂度O(n),因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。
另外由于list本身没有重载[]运算符,而vector有。而list的迭代器只重载了++运算符,所以对于list的迭代不能用+,+=等其它符号,只能使用++。而由于vector拥有一段连续的内存空间,能非常好的支持随机存取,因此vector<int>::iterator支持“+”、“+=”、“<”等操作符。
总结来说:
vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随即存取,而不在乎插入和删除的效率,使用vector。
list拥有一段不连续的内存空间,因此支持随机存取,如果需要大量的插入和删除,而不关心随即存取,则应使用list。