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 };