ACM-括号配对问题 ASCII码的运用|std::vector/std::list的区别与使用

描述
现在,有一行括号序列,请你检查这行括号是否配对。
输入
第一行输入一个数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。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值