classSolution{public:intlongestValidParentheses(string s){//首先明确,有效括号即任意前缀左括号不小于右括号,且整个串中两者数目相等//因此可以以每个刚开始不满足任意前缀左括号不小于右括号得位置为分界点,将整个串分组//那么有效括号串必然不可能跨越任意两组,因此在每组中更新最大长度就行int len = s.length(), res =0;
stack<int> stk;//栈中存放左括号下标//start代表分界点,起始位置分界点当然在0得左边即-1了for(int i =0, start =-1; i < len; i++){//每次s[i]两种情况 ( 或 )if(s[i]=='(') stk.push(i);else{//为右括号时,此时要配对,栈两种情况,空与非空if(stk.empty()) start = i;//空得话说明,开始不满足上面条件,即分界点else{
stk.pop();//先弹栈,弹栈后两种情况,空与非空//空了要想更新长度,只能减去分界点,非空就减去栈顶(为左边第一个还没匹配上得)就行//为什么减去栈顶呢,因为此时栈顶还没匹配上,因此栈顶为计算长度得分界点if(stk.empty()) res =max(res, i - start);else res =max(res, i - stk.top());}}}return res;}};
classSolution{public:intsearch(vector<int>& nums,int target){if(nums.empty())return-1;//先二分找到左边有序区间的右端点,依据:左边一定>=nums[0],右边<nums[0]int l =0, r = nums.size()-1;while(l < r){//为什么加1,个人理解,最后l,r一定会缩到相邻r=l+1,但是最终跳出循环的结果一定是l=r//所以这就要看要移动哪个,因为我们是将区间分为了[l,mid-1],[mid,r],而我们最终要找的//归在左边,所以要将r-1,那么就要把mid归在右边,即nums[mid]<nums[0],所以要加1//如[1,2],右端点左边显然1;l=0,r=1;如果不加1,mid永远为0,此时走的是l=mid,即永远l与r不相遇//那就不对了,所以+1,左边向右靠int mid = l + r +1>>1;//此时mid一定在左边有序区间,则向右包含该点查找端点if(nums[mid]>= nums[0]) l = mid;else r = mid -1;}//此时l=r等于左边有序区间右端点;两种情况,ta在左边,或右边if(target >= nums[0]) l =0;else l +=1, r = nums.size()-1;while(l < r){//此时为什么不加1,同理分析,因为区间分为[l,mid],[mid+1,r],mid归在左边//最后情况r=l+1时,所以r向左靠才可能找到taint mid = l + r >>1;if(nums[mid]>= target) r = mid;else l = mid +1;}//注意这里不能用nums[l],如当[1] 0时,即只有一个,r=1-1=0,l+=1越界;//只要时k=0的都会这样,如[1,2,3,4]最终lr都在3,如果ta=5,l加一越界,所以只有r永远不可能越界,用rif(nums[r]== target)return l;elsereturn-1;}};
classSolution{public:
vector<int>searchRange(vector<int>& nums,int target){if(nums.empty())return{-1,-1};int l =0, r = nums.size()-1, a =-1;//找分界点,左边的第一个,与右边最后一个//1.找左端点,[l,mid] [mid+1,r]while(l < r){int mid = l + r >>1;if(nums[mid]>= target) r = mid;else l = mid +1;}if(nums[r]== target)
a = r;elsereturn{-1,-1};//如果没有找到,就返回-1,-1//找右端点(能走到这里必然有,不会-1,-1)
l =0, r = nums.size()-1;while(l < r){int mid = l + r +1>>1;if(nums[mid]<= target) l = mid;else r = mid -1;}return{a, r};}};
classSolution{public:intsearchInsert(vector<int>& nums,int target){int l =0, r = nums.size()-1;//[l,mid], [mid+1,r]从左向右找到第一个>=target得值while(l < r){int mid = l + r >>1;if(nums[mid]>= target) r = mid;else l = mid +1;}//如果上面得r处值选size,直接return l就行,因为最终查的值范围[0,size],满足插入位置得所有可能情况//如果最终l所在值<ta,说明插入位置在右边if(nums[l]< target)return l +1;//如果=ta,l;>ta,插在l处return l;}};
classSolution{public:boolisValidSudoku(vector<vector<char>>& board){bool st[9];//检查每一行for(int i =0; i <9; i++){memset(st,0,sizeof st);for(int j =0; j <9; j++){if(board[i][j]!='.'){int a = board[i][j]-'1';if(st[a])returnfalse;
st[a]=true;}}}//检查每一列for(int i =0; i <9; i++){memset(st,0,sizeof st);for(int j =0; j <9; j++){if(board[j][i]!='.'){int a = board[j][i]-'1';if(st[a])returnfalse;
st[a]=true;}}}//检查每一个方块,(i,j)代表每个小方块得左上点for(int i =0; i <9; i +=3){for(int j =0; j <9; j +=3){memset(st,0,sizeof st);for(int x =0; x <3; x++){for(int y =0; y <3; y++){if(board[i + x][j + y]!='.'){int a = board[i + x][j + y]-'1';if(st[a])returnfalse;
st[a]=true;}}}}}returntrue;}};
classSolution{public:
string countAndSay(int n){
string s ="1";while(--n){
string t;for(int i =0; i < s.size();){int k = i +1;while(k < s.size()&& s[k]== s[i]) k++;
t +=to_string(k - i)+ s[i];
i = k;}
s = t;}return s;}};