125. 验证回文串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
示例 2:
输入: “race a car”
输出: false
思路一:
解法一:
class Solution {
public:
bool isPalindrome(string s) {
string s1;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == ' ')
{
i = s.find_first_not_of(' ',i);//从第i位置开始找第一个不为空格的位置
if(i==-1)
break;
}
if ((s[i] >= 'A'&&s[i] <= 'Z') || (s[i] >= 'a'&&s[i] <= 'z') || (s[i] >= '0'&&s[i] <= '9'))//是数字或者字母
{
if (s[i] >= 'A'&&s[i] <= 'Z')//大写转小写
{
s[i] = (s[i] + 32);
s1 = s1 + s[i];
}
else
{
s1 = s1 + s[i];
}
}
else continue;
}
string ress1 = s1;
std::reverse(ress1.begin(), ress1.end());//回转字符串
if (ress1 == s1)若相等
return true;
else return false;
}
};
该方法在字符串过大时,反转过程消耗过大的内存,故该方法在最后一个测试用例过不去。
解法2:双指针法:
isalnum(char c):判断字符变量c是否为字母或数字,若是则返回非零,否则返回零。
tolower(char c):把字母字符转换成小写,非字母字符不做出处理。
作者:chenlele
链接:https://leetcode-cn.com/problems/valid-palindrome/solution/yan-zheng-hui-wen-chuan-by-gpe3dbjds1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我的:
class Solution {
public:
bool isPalindrome(string s)
{
if(s.size()<=1)
{
return true;
}
int i = 0;
int j = s.size() - 1;
while(i < j)
{
while(i < j&&!isalnum(s[i]))
{
i++;
}
while(i < j&&!isalnum(s[j]))
{
j--;
}
if(tolower(s[i++])!=tolower(s[j--]))
{
return false;
}
}
return true;
}
};
20. 有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
想法一:
具体的思路就跟主流的思路一样,使用栈。
一.判断前括号还是后括号
1.前括号,压入。
2.后括号,判断是否可以pop和是否有匹配的前括号
二.此时循环结束,判断栈里是否还有残留
当然,中间的if对比还有可以优化的地方(可以有效减少对比的次数)
作者:haru-8
链接:https://leetcode-cn.com/problems/valid-parentheses/solution/cjie-fa-yong-shi-0ms-by-haru-8/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
ss.push(12);// 添加元素
ss.top();// 读取栈顶元素
ss.pop();// 弹出栈顶元素
我的:
class Solution {
public:
bool isValid(string s)
{
if(s==" ")
{
return true;
}
if(s.size()%2 != 0)
{
return false;
}
stack<char> ss;
for(auto i : s)
{
if(i=='{'||i=='('||i=='[')
{
ss.push(i);
}
else
{
if(ss.size() == 0 && (i == ']'||i == '}'||i == ')'))
{
return false;
}
else if((i == '}' && ss.top()!='{')||(i == ']' && ss.top()!='[')||(i == ')' && ss.top()!='('))
{
return false;
}
else
{
ss.pop();
}
}
}
if(ss.size()!=0)
{
return false;
}
return true;
}
};
28. 实现 strStr()
实现strStr()函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = “hello”, needle = “ll”
输出: 2
示例 2:
输入: haystack = “aaaaa”, needle = “bba”
输出: -1
说明:
当needle是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当needle是空字符串时我们应当返回0。这与C语言的strstr()以及Java的indexOf()定义相符。
想法一:
库函数解法:
BF算法 暴力破解:
时间复杂度O(M*N)
KMP解法:
时间复杂度O(M+N)
class Solution {
public:
vector<int> getnext(string str)
{
int len=str.size();
vector<int> next;
next.push_back(-1);//next数组初值为-1
int j=0,k=-1;
while(j<len-1)
{
if(k==-1||str[j]==str[k])//str[j]后缀 str[k]前缀
{
j++;
k++;
next.push_back(k);
}
else
{
k=next[k];
}
}
return next;
}
int strStr(string haystack, string needle) {
if(needle.empty())
return 0;
int i=0;//源串
int j=0;//子串
int len1=haystack.size();
int len2=needle.size();
vector<int> next;
next=getnext(needle);
while((i<len1)&&(j<len2))
{
if((j==-1)||(haystack[i]==needle[j]))
{
i++;
j++;
}
else
{
j=next[j];//获取下一次匹配的位置
}
}
if(j==len2)
return i-j;
return -1;
}
};
//KMP 的 next 数组可以进行优化,当字符失配时,回到相同字符无意义,应继续递归
BM算法:
时间复杂度最差和KMP一样 最佳是O(n)
class Solution {
public:
void get_bmB(string& T,vector<int>& bmB)//坏字符
{
int tlen=T.size();
for(int i=0;i<256;i++)//不匹配直接移动子串
{
bmB.push_back(tlen);
}
for(int i=0;i<tlen-1;i++)//靠右原则
{
bmB[T[i]]=tlen-i-1;
}
}
void get_suff(string& T,vector<int>& suff)
{
int tlen=T.size();
int k;
for(int i=tlen-2;i>=0;i--)
{
k=i;
while(k>=0&&T[k]==T[tlen-1-i+k])
k--;
suff[i]=i-k;
}
}
void get_bmG(string& T,vector<int>& bmG)//好后缀
{
int i,j;
int tlen=T.size();
vector<int> suff(tlen+1,0);
get_suff(T,suff);//suff存储子串的最长匹配长度
//初始化 当没有好后缀也没有公共前缀时
for(i=0;i<tlen;i++)
bmG[i]=tlen;
//没有好后缀 有公共前缀 调用suff 但是要右移一位 类似KMP里的next数组
for(i=tlen-1;i>=0;i--)
if(suff[i]==i+1)
for(j=0;j<tlen-1;j++)
if(bmG[j]==tlen)//保证每个位置不会重复修改
bmG[j]=tlen-1-i;
//有好后缀 有公共前缀
for(i=0;i<tlen-1;i++)
bmG[tlen-1-suff[i]]=tlen-1-i;//移动距离
}
int strStr(string haystack, string needle) {
int i=0;
int j=0;
int tlen=needle.size();
int slen=haystack.size();
vector<int> bmG(tlen,0);
vector<int> bmB;
get_bmB(needle,bmB);
get_bmG(needle,bmG);
while(i<=slen-tlen)
{
for(j=tlen-1;j>-1&&haystack[i+j]==needle[j];j--);
if(j==(-1))
return i;
i+=max(bmG[j],bmB[haystack[i+j]]-(tlen-1-j));
}
return -1;
}
};
Sunday 时间复杂度:
最坏为O(M*N) 平均复杂度为O(N)
class Solution {
public:
int strStr(string haystack, string needle) {
if(needle.empty())
return 0;
int slen=haystack.size();
int tlen=needle.size();
int i=0,j=0;//i指向源串首位 j指向子串首位
int k;
int m=tlen;//第一次匹配时 源串中参与匹配的元素的下一位
for(;i<slen;)
{
if(haystack[i]!=needle[j])
{
for(k=tlen-1;k>=0;k--)//遍历查找此时子串与源串[i+tlen+1]相等的最右位置
{
if(needle[k]==haystack[m])
break;
}
i=m-k;//i为下一次匹配源串开始首位 Sunday算法核心:最大限度跳过相同元素
j=0;//j依然为子串首位
m=i+tlen;//m为下一次参与匹配的源串最后一位元素的下一位
if(m>slen)//当下一次参与匹配的源串字数的最后一位的下一位超过源串长度时
return -1;
}
else
{
if(j==tlen-1)//若j为子串末位 匹配成功 返回源串此时匹配首位
return i-j;
i++;
j++;
}
}
return -1;//当超过源串长度时
}
};
作者:2227
链接:https://leetcode-cn.com/problems/implement-strstr/solution/c5chong-jie-fa-ku-han-shu-bfkmpbmsunday-by-2227/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我的:
class Solution {
public:
int strStr(string haystack, string needle)
{
if(needle.empty())
{
return 0;
}
int pos = haystack.find(needle);
return pos;
}
};
14. 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:所有输入只包含小写字母 a-z 。
思路一:
分析:
选择其中一个字符串作为对照标准,与后面的比较获得最长公共前缀res,再用res继续与后面的字符串比较,最后获得最终结果。
实现代码:
我的:
class Solution {
public:
string longestCommonPrefix(vector<string>& strs)
{
if(strs.empty())
{
return "";
}
string res = strs[0];
for (int i= 1;i<strs.size();i++)
{
for(int j=0;j<res.size();j++)
{
if(strs[i][j] == res[j])
{
continue;
}
else
{
res.erase(j);
break;
}
}
}
return res;
}
};