如果将所有大写字符转换为小写字符,并移除所有非字母数字后,正着读和反着读一样,就认为短语是一个回文串。
class Solution { public: bool isPalindrome(string s) { int left = 0; int right = s.size()-1; while(left < right){ while(left < right && !isalnum(s[left])){ left++; } while(left < right && !isalnum(s[right])){ right--; } if(left < right && tolower(s[left]) != tolower(s[right])){ return false; } left++; right--; } return true; } };
给定字符串s和t,判断s是否为t的子序列。
子序列是指原始字符串删除一些字符而不改变剩余字符相对位置形成的新字符串。
双指针
初始化两个指针i和j,分别指向s和t的初始位置。
每次贪心匹配,匹配成功则i和j同时右移,匹配s的下一个位置,匹配失败则j右移,i不变。
最终i移动到s的末尾,说明s是t的子序列。
class Solution { public: bool isSubsequence(string s, string t) { int n = s.size(); int m = t.size(); int sIndex = 0, tIndex = 0; while(sIndex < n && tIndex < m){ if(s[sIndex] == t[tIndex]){ sIndex++; tIndex++; }else{ tIndex++; } } return sIndex == n; } };
class Solution { public: vector twoSum(vector& numbers, int target) { int left = 0; int right = numbers.size()-1; while(left < right){ int num = numbers[left] + numbers[right]; if(num == target){ return {left+1, right+1}; }else if(num < target){ left++; }else{ right--; } } return {0,0}; } };
没有前后大小顺序关系,用双指针一般。
class Solution { public: bool canConstruct(string ransomNote, string magazine) { sort(ransomNote.begin(), ransomNote.end()); sort(magazine.begin(), magazine.end()); int i = 0, j = 0, m = ransomNote.size(), n = magazine.size(); while(i if(ransomNote[i] == magazine[j]){ i++; j++; }else{ j++; } } return i == m; } };
哈希表
class Solution { public: bool canConstruct(string ransomNote, string magazine) { unordered_map count; for(char c : magazine){ count[c]++; } for(char c : ransomNote){ if(count[c] == 0){ return false; }else{ count[c]--; } } return true; } };
数组
class Solution { public: bool canConstruct(string ransomNote, string magazine) { int count[26] = {}; for(char c : magazine){ count[c-'a']++; } for(char c : ransomNote){ if(count[c-'a'] == 0){ return false; }else{ count[c-'a']--; } } return true; } };
给两个字符串s和t,判断它们是否同构。
class Solution { public: bool isIsomorphic(string s, string t) { unordered_map s2t; unordered_map t2s; for(int i=0; i char x = s[i]; char y = t[i]; if((s2t.count(x) && s2t[x] != y) || (t2s.count(y) && t2s[y] != x)){ return false; } s2t[x] = y; t2s[y] = x; } return true; } };
vector splitString(string& str){ istringstream iss(str); vector res; string word; while(iss >> word){ res.push_back(word); } return res; }
class Solution { public: vector splitString(string s){ istringstream iss(s); vector res; string word; while(iss >> word){ res.push_back(word); } return res; } bool wordPattern(string pattern, string s) { unordered_map char2s; unordered_map s2char; vector words = splitString(s); if(pattern.size() != words.size()){ return false; } for(int i=0; i char c = pattern[i]; string word = words[i]; if((char2s.count(c) && char2s[c] != word) || (s2char.count(word) && s2char[word] != c)){ return false; } char2s[c] = word; s2char[word] = c; } return true; } };
class Solution { public: bool isValid(string s) { stack stk; for(int i = 0; i char ch = s[i]; if(ch == '(' || ch == '[' || ch == '{'){ stk.push(ch); }else{ if(stk.empty()){ return false; } char topCh = stk.top(); if((topCh =='[' && ch == ']') || (topCh =='(' && ch == ')') || (topCh =='{' && ch == '}')){ stk.pop(); }else{ return false; } } } return stk.empty(); } };
class Solution { public: bool isValid(string s) { int n = s.size(); if(n % 2 == 1){ return false; } unordered_map pairs = { {']','['}, {'}','{'}, {')','('} }; stack stk; for(char ch:s){ if(pairs.count(ch)){ if(stk.empty() || stk.top() != pairs[ch]){ return false; } stk.pop(); }else{ stk.push(ch); } } return stk.empty(); } };
我们首先将给定的字符串path根据/分割成一个由若干字符串构成的列表,记为names。
names中包含的字符串只能为以下几种:
对于空字符串以及一个点,无需处理。
对于两个点或者目录名,需要用一个栈来维护路径中的每一个目录名。当遇到两个点时,只要栈不为空,就切换到上一级(弹出栈顶目录),当遇到目录名时,就放入栈。
class Solution { public: vector splitString(string &path){ vector res; string temp; for(char c : path){ if(c == '/'){ res.push_back(temp); temp.clear(); }else{ temp += c; } } res.push_back(temp); return res; } string simplifyPath(string path) { vector names = splitString(path); vector stk; for(int i=0; i if(names[i] == ".."){ if(!stk.empty()){ stk.pop_back(); } }else if(!names[i].empty() && names[i] != "."){ stk.push_back(names[i]); } } string res; if(stk.empty()){ res = "/"; }else{ for(int i=0; i res += "/" + stk[i]; } } return res; } };
设计一个支持push,pop,top操作,并能在常数时间内检索到最小元素的栈。
辅助栈
class MinStack { stack stk; stack min_stk; public: MinStack() { min_stk.push(INT_MAX); } void push(int val) { stk.push(val); min_stk.push(min(min_stk.top(), val)); } void pop() { stk.pop(); min_stk.pop(); } int top() { return stk.top(); } int getMin() { return min_stk.top(); } }; /** * Your MinStack object will be instantiated and called as such: * MinStack* obj = new MinStack(); * obj->push(val); * obj->pop(); * int param_3 = obj->top(); * int param_4 = obj->getMin(); */
class Solution { public: int evalRPN(vector& tokens) { stack stk; for(int i=0; i if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){ int num2 = stk.top(); stk.pop(); int num1 = stk.top(); stk.pop(); if(tokens[i] == "+"){ stk.push(num1 + num2); }else if(tokens[i] == "-"){ stk.push(num1 - num2); }else if(tokens[i] == "*"){ stk.push(num1 * num2); }else{ stk.push(num1 / num2); } }else{ stk.push(stoi(tokens[i])); } } return stk.top(); } };
给一个字符串表达式s,请实现一个基本计算器来计算并返回它的值。
括号展开+栈
由于字符串除了数字与括号外,只有加号和减号两种运算符。
因此,如果展开表达式中所有的括号,则得到的新表达式中,数字本身不会发生变化,只是每个数字前面的符号会变化。
需要维护一个栈ops,其中栈顶元素记录了当前位置所处的每个括号的符号。
1+2+(3-(4+5)):
class Solution { public: int calculate(string s) { stack ops; ops.push(1); int sign = 1; int ret = 0; int i = 0; int n = s.size(); while(i < n){ if(s[i] == ' '){ i++; }else if(s[i] == '+'){ sign = ops.top(); i++; }else if(s[i] == '-'){ sign = -ops.top(); i++; }else if(s[i] == '('){ ops.push(sign); i++; }else if(s[i] == ')'){ ops.pop(); i++; }else{ long num = 0; while(i < n && s[i] >= '0' && s[i] <= '9'){ num = num * 10 + s[i]-'0'; i++; } ret += sign * num; } } return ret; } };
上一篇:Postman下载及使用说明
下一篇:vue脚手架配置代理请求