31、Next Permutation
题目
这道题目的意思是给定一个序列,找出其按照字典顺序的下一个顺序,如果给定顺序是字典中的最后一个顺序,其下一个顺序则为字典中的第一个顺序。比如:
1,2,3,4,5-----注,后面的顺序去掉逗号
12354
12435
12453
12534
12543
13245
通过上面的例子可以发现规律,在得到13245序列时,其实是从12543的右往左做比较,如果左边比右边数字大,继续往左比较,直到左边数字比右边小,比如12543中,2的右边都是递增的,直到2比5小,因此在543中从右往左找到第一个比2大的数3,交换2,3得到13542,然后将3之后的数字从小到大排序就是所得序列,代码如下:
1 class Solution { 2 public: 3 void nextPermutation(vector<int>& nums) { 4 const int size = nums.size(); 5 int temp,left,right; 6 if(size <= 1) 7 return; 8 9 if(2 == size) 10 { 11 temp = nums[0]; 12 nums[0] = nums[1]; 13 nums[1] = temp; 14 return; 15 } 16 17 int index = size-1-1;//从倒数第二个开始 18 19 while (index>=0) 20 { 21 if(nums[index] >= nums[index + 1])//等号很重要,比如(5,1,1)的情况 22 index--; 23 else 24 break; 25 } 26 27 28 29 if(index>=0) 30 { 31 right = size - 1; 32 while(right > index) 33 { 34 if(nums[right] <= nums[index])//等号很重要,比如(5,1,1)的情况 35 right--; 36 else 37 break; 38 } 39 40 if(right>index) 41 { 42 temp = nums[right]; 43 nums[right] = nums[index]; 44 nums[index] = temp; 45 } 46 left = (++index); 47 } 48 else 49 left = 0; 50 51 right = size-1; 52 53 while (left <= right) 54 { 55 temp = nums[right]; 56 nums[right] = nums[left]; 57 nums[left] = temp; 58 left++; 59 right--; 60 } 61 62 } 63 };
-----------------------------------------------------------------------------------------------------分割线-----------------------------------------------------------------------
32、Longest Valid Parentheses
题目
这道题在具体实现的时候,大家第一反应肯定是要用到stack结构,因为在这种成对匹配的题型中,stack是首选的数据结构。仔细分析题目可得知,题目要求找出最长的合法括号对子串,这道题难点在于需要分析会出现的错误种类,经过分析总结,可以得出如下的错误种类:
1、当遍历到字符串当前字符s[index] ==')'并且stack是空的,也就是说,字符串s从0到index-1的字符都能两两匹对,比如“()()())xxxxx”中,index=6时就是这种情况,针对这种情况,如果我事先已经知道了index之前的字符串中合法子串的最大长度,为max,那么从index+1又可看作是一个新的、从"0"开始处理的字符串s';并且问题规模比之前的s更小了;
2、第二种错误种类不能从当前字符来判断,这种错误类型是这中模式s="--------(----(----",s中多出了两个左括号,其他部分都是刚好匹配的合法串;
通过上面的描述,下面用比较正规的描述一下这几种错误:
a、假设X是左右括号刚好匹配的字符串,比如"()()"、"(())"等,X可以是空串,s'是s的子串,s'也可以是空串;
b、错误模式一:s = “X)s'”;
c、错误模式二:s = “X(s'”;
d、除了这两种类型,没有其他的错误类型了;
有人会问s="X)(s'"是哪一种,其实这种错误时两种错误的结合,拆分为"X)"和"(s‘"即可;
针对错误模式一,只需要保存好X的长度,然后从s’开始下一轮算法执行,而s'是比s规模更小的串;
针对错误模式二,需要比较s'的最长合法子串和X的长度,然后进行比较,比如s="--------(----(----",我只需要在栈中保存好这两个多余的左括号的下标,然后从字符串的末尾开始,从栈中弹出栈顶下标(其实就是s中第二个多余字符的下标)index,end-index就是合法字符串的长度,及第二个左括号右边那部分的长度,接着end赋值为index-1,重复如此计算得到最后的结果;
代码如下:
1 class Solution { 2 public: 3 int longestValidParentheses(string s) { 4 if(""==s) 5 return 0; 6 stack<int> myStack; 7 int index = 0; 8 int res=0; 9 int start=0,end; 10 int temp; 11 12 while (s[index]!='\0') 13 { 14 if('(' == s[index]) 15 { 16 myStack.push(index); 17 } 18 else 19 { 20 if(myStack.empty())//错误模式一 21 { 22 if(index - start > res) 23 res = index - start; 24 start = index+1; 25 } 26 else 27 { 28 myStack.pop(); 29 } 30 } 31 index++; 32 } 33 end =index-1; 34 if(myStack.empty()) 35 { 36 if(end - start+1 > res ) 37 res = end -start+1; 38 39 return res; 40 } 41 while(!myStack.empty()) 42 { 43 temp = myStack.top(); 44 myStack.pop(); 45 if(end - temp > res) 46 res = end -temp; 47 48 end = temp-1; 49 } 50 51 if(end - start+1 > res) 52 res = end -start+1; 53 return res; 54 } 55 };