文章目录
字符串:
反转字符串
题意:
如题,要求原地算法
解:
下标变换或者函数reverse
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/*
void reverseString(vector<char>& s)
{
int lg=s.size();
for(int i=0;i<lg/2;i++) swap(s[i],s[lg-i-1]);
}*/
void reverseString(vector<char>& s)
{
reverse(s.begin(),s.end());
}
int main()
{
vector<char> chars;char ch;
while(cin>>ch)
{
chars.push_back(ch);
}
reverseString(chars);
for(auto &achar:chars) cout<<achar<<ends;
cout<<endl;
return 0;
}
整数反转
题意:
要求反转一个32位整数,如果溢出返回0,机器不允许使用64整数
解:
由于不允许64整数那么就用unsigned或者string存储,毕竟是字符串题而且方便翻转
注意点:
1、力扣提供函数为reverse,使用标准库函数需要添加std::
(DEV跑的时候我没加,最后CE了)
2、String2Int
函数内 ans=10*ans+(s[i]-'0');
不能使用 ans=10*ans+s[i]-'0';
优先级导致溢出
3、字符串比较溢出的时候需要确认长度,详见字符串比较方式(从头到尾的字典序比较)
代码:
#include<bits/stdc++.h>
using namespace std;
int String2Int(string s)
{
int lg=s.length(),i=0,ans=0;
if(s[0]=='-') i++;
for(;i<lg;i++)
{
ans=10*ans+(s[i]-'0');
}
if(s[0]=='-') ans*=-1;
return ans;
}
int reverse(int x)
{
string s,MIN_INT,MAX_INT;
MIN_INT=to_string(INT_MIN);
MAX_INT=to_string(INT_MAX);
s=to_string(x);
if(x<0)
{
std::reverse((s.begin()+1),s.end());
if(s.length()==MIN_INT.length() && s>MIN_INT) return 0;
}
else
{
std::reverse(s.begin(),s.end());
if(s.length()==MAX_INT.length() && s>MAX_INT) return 0;
}
int ans=String2Int(s);
return ans;
}
int main()
{
int temp;cin>>temp;
int ans=reverse(temp);
cout<<ans<<endl;
return 0;
}
字符串中的第一个唯一字符
题意:
如题,第一个是唯一存在的字符
解:
用点简单的,index记录出现的下标,由于下标>=0所以特设-1为不存在(还没遇见),-2为出现超过一次
全都是小写字符可以直接转下标去访问数组
代码:
#include<bits/stdc++.h>
using namespace std;
int firstUniqChar(string s)
{
int index[26],lg=s.length(),ans=INT_MAX;
memset(index,-1,sizeof index);
for(int i=0;i<lg;i++)
{
int num=s[i]-'a';
if(index[num]==-1) index[num]=i;
else if(index[num]>=0) index[num]=-2;
}
for(int i=0;i<26;i++)
{
if(index[i]>=0) ans=min(ans,index[i]);
}
return (ans==INT_MAX?-1:ans);
}
int main()
{
string s;cin>>s;
int ans=firstUniqChar(s);
cout<<ans<<endl;
return 0;
}
有效的字母异位词
题意:
判断两个字符串是否拥有相同种数的字母,每种字母数量是否相同
解:
记个数
代码:
#include<bits/stdc++.h>
using namespace std;
bool isAnagram(string s, string t)
{
int lgs=s.length(),lgt=t.length();
if(lgs!=lgt) return false;
vector<int>nums(26);
for(auto ch:s) nums[(ch-'a')]++;
for(auto ch:t) nums[(ch-'a')]--;
for(auto num:nums) if(num!=0) return false;
return true;
}
int main()
{
string s,t;cin>>s>>t;
bool ans=isAnagram(s,t);
cout<<ans<<endl;
return 0;
}
验证回文串
题意:
判断一个字符串移除所有非字母数字,将大写字母变成小写字母后是否是一个回文串
解:
双指针,字符处理
代码:
#include<bits/stdc++.h>
using namespace std;
bool check(char a)
{
if((a>='0' && a<='9')||(a>='a' && a<='z')||(a>='A' && a<='Z')) return true;
return false;
}
bool isPalindrome(string s)
{
int lg=s.length();
for(int i=0;i<lg;i++) if(s[i]>='A' && s[i]<='Z') s[i]=s[i]-'A'+'a';
for(int l=0,r=lg-1;l<r;l++,r--)
{
while(l<lg && !check(s[l])) l++;
while(r>=0 && !check(s[r])) r--;
if(r<0||l>=lg) break;
//cout<<l<<" "<<r<<endl;
if(s[l]!=s[r]) return false;
}
return true;
}
int main()
{
string s;
getline(cin,s);
bool ans=isPalindrome(s);
cout<<ans<<endl;
return 0;
}
字符串转换整数 (atoi)
题意:
如题,具体规则不写了
解:
状态机获取字符串,去除前缀零和对只有符号的字符串补零,字符串比较防止溢出
我这个写法虽然繁琐了点但是不需要用到LongLong,虽然如官方题解一样可以通过INT_MAX
除以 10 进行比较防止移除,但是还要考虑加法溢出,不如直接用字符串比较
代码:
#include<iostream>
#include<cstring>
#include<climits>
using namespace std;
int String2Int(string s)
{
int lg=s.length(),i=0,ans=0;
if(s[0]=='-') i++;
for(;i<lg;i++)
{
ans=10*ans+(s[i]-'0');
}
if(s[0]=='-') ans*=-1;
return ans;
}
void solve(string &s)
{
if(s[0]=='-')//负数
{
while(s.size()>=2 && s[1]=='0') s.erase(1,1);
if(s.size()==1) s.push_back('0');
}
else
{
while(s.size()>=1 && (s[0]=='+'||s[0]=='0')) s.erase(0,1);
if(s.empty()) s.push_back('0');
}
}
int myAtoi(string s)
{
string temp,num;
int ans=0,step=0;
for(auto &ch:s)
{
if(step==0)//阶段0
{
if(ch==' ') continue;
else if(ch=='+'||ch=='-'|| (ch>='0'&&ch<='9') )
{
step=1;
temp.push_back(ch);
}
else break;
}
else if(step==1 && (ch>='0'&&ch<='9') )//阶段1
{
temp.push_back(ch);
}
else break;
}
solve(temp);
if(temp[0]=='-')//负数
{
string MIN_INT=to_string(INT_MIN);
if(temp.length()<MIN_INT.length()) return String2Int(temp);
else if(temp.length()==MIN_INT.length())
{
if(temp<MIN_INT) return String2Int(temp);
else return INT_MIN;
}
else return INT_MIN;
}
else
{
string MAX_INT=to_string(INT_MAX);
if(temp.length()<MAX_INT.length()) return String2Int(temp);
else if(temp.length()==MAX_INT.length())
{
if(temp<MAX_INT) return String2Int(temp);
else return INT_MAX;
}
else return INT_MAX;
}
return 0;
}
int main()
{
string s;
getline(cin,s);
int ans=myAtoi(s);
cout<<ans<<endl;
return 0;
}
实现 strStr()
题意:
在s1中找s2的最小下标,找不到返回-1
解:
经典的字符串匹配,暴力和KMP,小小写了一下KMP,好久没用了
代码:
#include<bits/stdc++.h>
using namespace std;
void get_next(const string &needle,vector<int> &next)
{
int m1=1,m2=0;//m1表示主串位置,m2表示已经匹配的字符数量
while(m1<needle.size())
{
while(m2>0 && needle[m1]!=needle[m2]) m2=next[m2];
if(needle[m1]==needle[m2]) m2++;
next[++m1]=m2;
}
//for(auto n:next) cout<<n<<ends;
//cout<<endl;
}
int strStr(const string haystack,const string needle)
{
int lg1=haystack.length(),lg2=needle.length();
if(lg1<lg2) return -1;
vector<int>next(lg2+1);//next存储匹配i失败时跳转至next[i-1]
get_next(needle,next);
int m1=0,m2=0;//m1表示主串位置,m2表示已经匹配的字符数量
while(m1<lg1 && m2<lg2)
{
//cout<<m1<<" "<<m2<<endl;
if(haystack[m1]==needle[m2])//匹配下一个
{
//cout<<m1<<"=="<<m2<<endl;
m1++;m2++;
if(m2==lg2) return m1-m2;
}
else//匹配失败
{
if(m2==0) m1++;
m2=next[m2];
}
}
return -1;
}
int main()
{
string s1,s2;cin>>s1>>s2;
int ans=strStr(s1,s2);
cout<<ans<<endl;
return 0;
}
外观数列
题意:
略
解:
简单字符串处理+递归/迭代
代码:
#include<iostream>
using namespace std;
string solve(const string n)
{
cout<<n<<endl;
char ch=n[0];int lg=n.size(),num=0;
string ans;
for(int i=0;i<lg;i++)
{
if(n[i]==ch)
{
num++;
}
else
{
ans=ans+to_string(num);
ans.push_back(ch);
num=1;ch=n[i];
}
}
ans=ans+to_string(num);
ans.push_back(ch);
//cout<<"ans:"<<ans<<endl;
return ans;
}
string countAndSay(int n)
{
string ans="1";
for(int i=1;i<n;i++)
{
ans=solve(ans);
}
return ans;
}
/*
string countAndSay(int n)
{
if(n==1) return "1";
return solve(countAndSay(n-1));
}*/
int main()
{
int n;cin>>n;
string ans=countAndSay(n);
cout<<ans<<endl;
return 0;
}
最长公共前缀
题意:
如题
解:
先排序可以把最短的放最前面,这样最长前缀的长度一定小于等于这个最短的字符串,其他的暴力
代码:
#include<bits/stdc++.h>
using namespace std;
string solve(const string &s1,const string &s2)
{
string ans;
int lg=min(s1.size(),s2.size());
for(int i=0;i<lg;i++)
{
if(s1[i]==s2[i]) ans.push_back(s1[i]);
else break;
}
return ans;
}
string longestCommonPrefix(vector<string>& strs)
{
sort(strs.begin(),strs.end());
int lg=strs.size();
if(lg==1) return strs[0];
string ans=solve(strs[0],strs[1]);
for(int i=2;i<lg;i++)
{
ans=solve(ans,strs[i]);
if(ans.empty()) break;
}
return ans;
}
int main()
{
vector<string>strs;string str;
while(cin>>str)
{
strs.push_back(str);
}
string ans=longestCommonPrefix(strs);
cout<<ans<<endl;
return 0;
}