C++学习笔记(十二)——String类练习题(下)

                                 未来属于那些相信梦想并愿意为之付诸行动的人

                                                 


仅仅反转字母

字符串中的第一个唯一字符 

字符串最后一个单词的长度 

验证回文串

字符串相加 

反转字符串|| 

反转字符串中的单词||| 

字符串相乘​

找出字符串中第一个只出现一次的字符 


仅仅反转字母

双指针 

我们使用 left 指针从左边开始扫描字符串s, right指针从右边开始扫描字符串 s。如果两个指针都扫描到字母,且 left<right,那么交换 s[left] 和 s[right],然后继续进行扫描;否则表明反转过程结束,返回处理后的字符串。

class Solution {
public:
    bool letter(char ch)
    {
        if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
        {
            return true;
        }
        else{
            return false;
        }
    }
    string reverseOnlyLetters(string s) {
    int begin=0;
    int end=s.size()-1;
     while(begin<end)
     {
      while(begin<end&&!letter(s[begin]))
      {
         ++begin;
      }
      while(begin<end&&!letter(s[end]))
      {
          --end;
      }
      swap(s[begin],s[end]);
      ++begin;
      --end;
     }
     return s;
    }
};

哈希表

class Solution {
public:
    string reverseOnlyLetters(string s) {
     map<int,char> no;
     int len=s.size()-1;
     string m;
     for(int i=len;i>=0;i--)
     {
         if(isalpha(s[i]))
         {
            m+=s[i];
         }
         else{
            no[i]=s[i];
         }
     }
     for(auto it=no.begin();it!=no.end();it++)
     {
         m.insert(it->first,1,it->second);
     }
     return m;
    }
};

用栈处理

class Solution {
public:
   //栈
    string reverseOnlyLetters(string s) {
      stack<char> a;
      int len=s.size()-1;
      string m;
      for(int i=0;i<=len;i++)
      {
          if(isalpha(s[i]))
          {
             a.push(s[i]);
          }
      }
      for(int i=0;i<=len;i++)
      {
          char ch;
         if(isalpha(s[i]))
         {
          ch=a.top();
          a.pop();
         }
         else{
             ch=s[i];
         }
         m+=ch;
      }
      return m;
    }
};

字符串中的第一个唯一字符

数组下标 

class Solution {
public:
    int firstUniqChar(string s) {
    int count[26]={0};
    int len=s.size()-1;
    for(int i=0;i<=len;i++)
    {
        count[s[i]-'a']++;
    }
    for(int i=0;i<=len;i++)
    {
        if(count[s[i]-'a']==1)
        {
            return i;
        }
    }
    return -1;
    }
};

哈希表 

class Solution {
public:
    int firstUniqChar(string s) {
     unordered_map<char,int> a;
     int len=s.size()-1;
     for(int i=0;i<=len;i++)
     {
         a[s[i]]++;
     }
     for(int i=0;i<=len;i++)
     {
         if(a[s[i]]==1)
         {
             return i;
         }
     }
     return -1;
    }
};

字符串最后一个单词的长度

#include<iostream>
using namespace std;
int  main()
{
   string s;
  while(getline(cin,s))
  {
      int pos=s.rfind(' ');
      cout<<s.size()-1-pos<<endl;
  }
    return 0;
}

验证回文串

class Solution {
public:
    bool isletter(char ch)
    {
       //判断是否是字母或者是数字
        if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
        {
            return true;
        }
        else{
            return false;
        }
    }
    bool isPalindrome(string s) {
       //先把大写字母转换成小写字母
        for(auto& ch:s)
        {
            if(ch>='a'&&ch<='z')
            {
                ch-=32;
            }
        }
      int begin=0,end=s.size()-1;
      while(begin<end)
      {
       //判断是否是字母或者是数字,不是就一直走
          while(begin<end&&!isletter(s[begin]))
          {
              ++begin;
          }
          while(begin<end&&!isletter(s[end]))
          {
              --end;
          }
      //当到这里,说明这两个数是字母或者数字,判断是否相等
          if(s[begin]!=s[end])
          {
              return false;
          }
       //如果相等继续移动指针比较后面的,如果不相等,上一步直接返回false
          else{
              ++begin;
              --end;
          }
      }
      return true;
    }
};

字符串相加

class Solution {
public:
   //大数相加
   //从后往前加+=,以后再用reverse反转过来
   // 123
  // + 48
    string addStrings(string num1, string num2) {
     int end1=num1.size()-1;
     int end2=num2.size()-1;
     int value1=0,value2=0,next=0;
     int  addret=0;
     string sum;
     while(end1>=0||end2>=0)
     {
         if(end1>=0)
         {
          value1=num1[end1--]-'0';
         }
         else{
             value1=0;
         }
         if(end2>=0)
         {
             value2=num2[end2--]-'0';
         }
         else{
             value2=0;
         }
         addret=value1+value2+next;
         if(addret>9)
         {
             next=1;
             addret-=10;
         }
         else{
             next=0;
         }
         sum+=(addret+'0');
     }
     if(next==1)
     {
         sum+='1';
     }
       reverse(sum.begin(),sum.end());
        return sum;
    }
};

反转字符串||

 我们直接按题意进行模拟:反转每个下标从 2k2k 的倍数开始的,长度为 kk 的子串。若该子串长度不足 kk,则反转整个子串。

class Solution {
public:
    string reverseStr(string s, int k) {
        int n = s.length();
        for (int i = 0; i < n; i += 2 * k) {
            reverse(s.begin() + i, s.begin() + min(i + k, n));
        }
        return s;
    }
};

反转字符串中的单词|||

class Solution {
public:
    string reverseWords(string s) {
        if(s.size()==1||s.size()==0) return s;  //如果s的长度为0或者1就没必要有后续了;
        int i = 0, j = 0;     //定义“双指针”吧,i后面用来指向单词end(),j用来指向单词第一个;
        for(auto ch:s){
            if(ch==' '){
           reverse(&s[j],&s[i]);   //翻转单词
           j=i+1;      //反复指向单词首个字符
            }
            ++i;
        }
if(s[s.size()-1]!=' ')     //如果最后一个单词最后字符不是空格,那还得翻转一次
        reverse(&s[j],&s[i]);
      return s;
    }
};

字符串相乘

在相乘或者相加计算过程的每一位,我们可以考虑先不去满10进位,等到计算完所有的相乘结果以后,最终将其加到一块,再去满10进位 ,最后的结果和普通竖式 一样,但却可以大大简化我们的模拟过程。(如下图所示)

1、长度是n和长度是m的数字相乘,最多只有n + m位,为了方便计算,将num1和num2反向存储到A[]和B[]中,即位数低的在数组前面,且开一个大小是n + m的C[]存储计算后的答案。
2、两个数相乘时,将A[i] * B[j]的结果累加到C[i + j]中,最后C[i + j]表示i + j这个位数的值是C[i + j](如上图所示)
3、由于C[]数组中的某些位数字可能是大于等于10的,我们从0枚举到n + m - 1,进行满10进位, 将所有位的值全部变成个位数。
4、最后将C[]数组反转输出。

class Solution {
public:
    string multiply(string num1, string num2) {
        vector<int> A, B;
        int n = num1.size(), m = num2.size();
        for (int i = n - 1; i >= 0; i -- ) A.push_back(num1[i] - '0'); //反向存贮
        for (int i = m - 1; i >= 0; i -- ) B.push_back(num2[i] - '0');
        vector<int> C(n + m);
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ )
                C[i + j] += A[i] * B[j];
        int t = 0;  //存贮进位
        for (int i = 0; i < C.size(); i ++ ) {
            t += C[i];
            C[i] = t % 10;
            t /= 10;
        }
        int k = C.size() - 1;
        while (k > 0 && !C[k]) k -- ;  //去除前导0
        string res;
        while (k >= 0) res += C[k -- ] + '0';  //反转
        return res;
    }
};

找出字符串中第一个只出现一次的字符

这一题和上面一题极为相似,那题我用了数组下标做的,这题当然也是可以,不过换个思路做,拓展下知识面. 

#include<iostream>
using namespace std;
int main()
{
    string s;
    while(getline(cin,s))
    {
        for(int i=0;i<s.size();i++)
        {
            if(s.find_first_of(s[i])==s.find_last_of(s[i]))//从前往后找,从后往前找,如果是同 
       一个数那说明这个是第一个只出现了一次,返回该字母
            {
                cout<<s[i]<<endl;
                break;
            }
//如果走到最后还没有找到,说明没有,返回-1
            if(i==s.size()-1)
            {
                cout<<-1<<endl;
              }
        }
    }
    return 0;
}

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

接受平凡 努力出众

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值