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

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

仅仅反转字母


image.png

双指针

我们使用 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;
    }
};

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


image.png

数组下标

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;
    }
};

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


image.png

#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;
}

验证回文串


image.png

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;
    }
};

字符串相加


df84e23ad1ac412b880ce915be7e1e21.png

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;
    }
};

反转字符串||


image.png

我们直接按题意进行模拟:反转每个下标从 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;
    }
};

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


image.png

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;
    }
};

字符串相乘


image.png

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

32e29166e78ea9f08ed350bd84b746e6.png

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;
    }
};

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


image.png

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

#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;
}


相关文章
|
19天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
44 5
|
19天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
29 2
|
25天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
59 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
65 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
74 4
|
2月前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
43 2
|
2月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
30 4
|
2月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
26 4
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
25 1
|
2月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)

热门文章

最新文章