初级算法-字符串

字符串:

反转字符串
题意:

如题,要求原地算法

解:

下标变换或者函数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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值