leetcode20——有效的括号
题目描述:
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()" 输出:true
示例 2:
输入:s = "()[]{}" 输出:true
示例 3:
输入:s = "(]" 输出:false
算法思想:
依次扫描字符串遇到左括号入栈,遇到右括号检查栈顶是否为对应的左括号,如果对应弹出栈顶元素,不对应返回false。若最后栈空则返回true。
算法实现:
bool isValid(string s) {
int slen=s.size();
//长度为奇数,一定不能匹配成功
if(slen%2==1) return false;
stack<char> stack1;
for(int i=0;i<s.size();i++){
//左括号入栈
if(s[i]=='(' || s[i]=='{' || s[i]=='[' ) stack1.push(s[i]);
//右括号的处理
else if(s[i]==')'){
if(stack1.empty() || stack1.top()!='(') return false;
stack1.pop();
}
else if(s[i]=='}'){
if(stack1.empty() || stack1.top()!='{') return false;
stack1.pop();
}
else if(s[i]==']'){
if(stack1.empty() || stack1.top()!='[') return false;
stack1.pop();
}
}
//检查最后栈是否为空
return stack1.empty();
}
leetcode1047——删除字符串中的所有相邻重复项
题目描述:
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
算法思想:
初始化一个字符空栈,依次遍历字符串的每个字符,若栈为空直接将字符入栈。若不为空检查当前字符与字符栈顶元素是否相同,若相同弹出栈顶元素且该元素不入栈,若不相同则该元素入栈。最后栈中的元素即为要返回的最终字符的倒叙。
算法实现:
string removeDuplicates(string s) {
//用字符串代替上述栈,直接得到正序结果
string res;
for(char c:s){
if(res.empty() || c!=res.back()) {
res.push_back(c);
}
else if(c==res.back()) {
res.pop_back();
}
}
return res;
}
leetcode150——逆波兰表达式求值
题目描述:
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"] 输出:6 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
算法思想:
初始化一个空的数字栈,依次遍历字符串数组,若不为运算符将该字符串转成int型入栈。若为运算符依次弹出数字栈的两个元素为a、b,并进行相应的运算(b运算符a)并将结果压入栈中,直至遍历完整个字符串数组,最终栈里保存的结果即为所求。
算法实现:
int evalRPN(vector<string>& tokens) {
stack<int> nums;
int a,b;
for(auto s:tokens){
if(s!="+" && s!="-" && s!="*" && s!="/"){
nums.push(stoi(s));
}
else{
a=nums.top();
nums.pop();
b=nums.top();
nums.pop();
if(s=="+") nums.push(b+a);
else if(s=="-") nums.push(b-a);
else if(s=="*") nums.push(b*a);
else nums.push(b/a);
}
}
return nums.top();
}
leetcode239——滑动窗口最大值
题目描述:
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1 输出:[1]
算法思想:
初始化一个双端队列,队头始终存放窗口的最大值。每遍历下一个窗口时检查要移除的元素(当前窗口的头部)是否为队头元素,若是则队头出队,若不是则不做操作;检查要入队的元素(下一个窗口的尾部)是否比队尾元素大,若大则队尾元素出队直至到小于队尾元素再将该元素入队,若小直接入队。将每次的队头元素分别加入到要返回的数组中即为答案。
算法实现:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
deque<int> que;
for(int i=0;i<k;i++){
while(!que.empty() && nums[i]>que.back()) que.pop_back();
que.push_back(nums[i]);
}
res.push_back(que[0]);
for(int i=0;i+k<nums.size();i++){
if(nums[i]==que[0]) que.pop_front();
while(!que.empty() && nums[i+k]>que.back()) que.pop_back();
que.push_back(nums[i+k]);
res.push_back(que[0]);
}
return res;
}