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天前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
165 5
|
8月前
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
4月前
|
对象存储 C++ 容器
c++的string一键介绍
这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。那么废话少说直接开始进行挨个介绍。
94 3
|
4月前
|
存储 编译器 C语言
关于string的‘\0‘与string,vector构造特点,反迭代器与迭代器类等的讨论
你真的了解string的'\0'么?你知道创建一个string a("abcddddddddddddddddddddddddd", 16);这样的string对象要创建多少个对象么?你知道string与vector进行扩容时进行了怎么的操作么?你知道怎么求Vector 最大 最小值 索引 位置么?
99 0
|
7月前
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
169 11
|
7月前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、&quot;+&quot;操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
185 9
|
8月前
|
C++
模拟实现c++中的string
模拟实现c++中的string
|
7月前
|
存储 JavaScript Java
课时44:String类对象两种实例化方式比较
本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。 1.直接赋值的对象化模式 2.字符串池的概念 3.构造方法实例化
111 1
|
11月前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
454 5
|
8月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。