C++算法(二)

༺ 个人主页 · 纪念229 ༻

🏠我的博客主页🏠

༒专栏目录:《数据结构》༒

༒专栏目录:《算法》༒

༒专栏目录:《C++》༒

༒专栏目录:《MySQL数据库》༒

༒专栏目录:《前端开发》༒

༒其它有趣的计算机知识༒

༺世上本没有路,走的人多了自然就有了༻


本文讲述的是string类的OJ题,希望对你有所帮助

后面可能还会讲一些有关C++内存分布的题

题目链接:

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

验证一个字符串是否是回文

翻转字符串


文章目录


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

题目是核心代码模式

我们看到题目里测试的字符串全是小写字符我们可以创建一个26个元素的整型数组来计出现的小写字符(我们知道查到的小写字符a~z减a在下标0-25之间)个数(遍历字符数组给计数数组计数),最后利用数组和s得到第一个计数为一的唯一字符并利用下标返回该下标(遍历字符数组利用计数数组返回第一个唯一字符)

c 复制代码
class Solution {
public:
    int firstUniqChar(string s) {
    //因为题目通常只包括小写字母,可以为大小为26的数组代替哈希表
    //通过小写字母26个字符形成数组将字符串中字符个数记好
    //然后遍历这个26数组将第一个数据为1的下标返回
    int count[26] = {0};
    

    //第一次遍历,统计每个字符出现的个数
    //统计每个字符出现的个数可以用范围for
    for(char e : s)
    {
        count[e - 'a']++;
    }
     
    //第二次遍历,返回count数组中数据为1的s上的下标(通过遍历s数组利用count数组)
    //用s[i] - 'a'就可以得到count数组的下标
    //用范围for返回不了下标
    for(int i = 0; i < s.length(); i++)
    // 中间要写范围for(int i = 0; s.length(); i++)

    {
        //这里是通过数组count计数小写字母最后遍历数组s将其减'a'来判断count数组里是否有为1的数据如果有就将当时遍历在s上的下标返回如果没有就返回-1
        if(count[s[i] - 'a'] == 1)
        return i; 
    }

    //如果count中没有为1的数据就返回-1
    return -1;
    }
}; 

int count[26] = {0};

创建一个计数数组

c 复制代码
 for(char e : s)
    {
        count[e - 'a']++;
    }

这里遍历字符数组string因为用不上下标用范围for遍历方便

将遍历的字符与'a'相减得到下标0~25之间的下标进行计数加加

c 复制代码
for(int i = 0; i < s.length(); i++)
    // 中间要写范围for(int i = 0; s.length(); i++)

    {
        //这里是通过数组count计数小写字母最后遍历数组s将其减'a'来判断count数组里是否有为1的数据如果有就将当时遍历在s上的下标返回如果没有就返回-1
        if(count[s[i] - 'a'] == 1)
        return i; 
    }

遍历字符数组用for循环遍历得到第一个唯一字符

if(count[s[i] - 'a'] == 1)

这里也是将s数组中的字符减'a'得到下标指向的数据是否为1(为一就返回字符数组此时遍历的下标)

return -1;

如果计数数组没有为一的数据就返回-1表示没找到(题目示例中有)


2.验证一个字符串是否是回文

这里就是注意两点:

1.仔细看题我看成是将大写字符转换为小写将小写字符和数字字符(我没记数字字符)放入另一个数组中然后判断回文

注意小写字符和数字字符之间的关系是||不能是&&(没有既是字母字符又是数字字符的字符)

2.大写字符加32就是它的小写字符(我写成了大写字符减去32是它的小写字符(错误))

题目是核心代码模式

c 复制代码
bool ispr(string s)
{
  


    for(int i = 0; i < s.size(); i++)
    {
        if(s[i] >= 'A' && s[i] <= 'Z')
        // if(s[i] >= A && s[i] <= Z) 字符要加''否则会当成名字
        {
           s[i]  += 32;
        //    s[i]  -= 32;大写字母加32才是小写字母
        }
    }
 

   
    
     string s1 = s;


    int i = 0;
    for(int j = 0 ; j < s.size() ; j++)
    {
        if(s[j] >= 'a' && s[j] <= 'z' || s[j] >= '0' && s[j] <= '9')
        
        // if(s[j] >= 'a' && s[j] <= 'z' && s[j] >= '0' && s[j] <= '9')这里字符不可能既是字母字符又是数字字符所以要用||
        // if(s[j] >= 'a' && s[j] <= 'z' )这里除了管字符还有数字
        {
            s1[i] = s[j];
            i++;
            //这个i不仅是下标它还作为s1的有效字母个数进行判断回文
        }
    }

    //i等于1或0都是回文直接返回true;
    

    int left = 0,right = i - 1;
    while(left < right)
    {
        if(s1[left] != s1[right])
        {
            return false;
        }
        left++;
        right--;
        // right++;这里right是--不是++
    }
    return true;
}








class Solution {
public:
    bool isPalindrome(string s) {
        return ispr(s);
    }
};
c 复制代码
for(int i = 0; i < s.size(); i++)
    {
        if(s[i] >= 'A' && s[i] <= 'Z')
        // if(s[i] >= A && s[i] <= Z) 字符要加''否则会当成名字
        {
           s[i]  += 32;
        //    s[i]  -= 32;大写字母加32才是小写字母
        }
    }

这里也可以用范围for

首先将字符数组中的大写字符(e >='A' && e <= 'Z' )加32变成小写字符

c 复制代码
 string s1 = s;


    int i = 0;
    for(int j = 0 ; j < s.size() ; j++)
    {
        if(s[j] >= 'a' && s[j] <= 'z' || s[j] >= '0' && s[j] <= '9')
        
        // if(s[j] >= 'a' && s[j] <= 'z' && s[j] >= '0' && s[j] <= '9')这里字符不可能既是字母字符又是数字字符所以要用||
        // if(s[j] >= 'a' && s[j] <= 'z' )这里除了管字符还有数字
        {
            s1[i] = s[j];
            i++;
            //这个i不仅是下标它还作为s1的有效字母个数进行判断回文
        }
    }

先使用拷贝构造拷贝一个字符数组,在定义一个int类型的i为0遍历赋值,最后作为有效数据进行进行回文判断

注意这里要放的是字母字符和数字字符(sj >= 'a' && sj <= 'z' || sj >= '0' && sj <= '9' )

字母字符与数字字符之间是||不是&&

c 复制代码
 int left = 0,right = i - 1;
    while(left < right)
    {
        if(s1[left] != s1[right])
        {
            return false;
        }
        left++;
        right--;
        // right++;这里right是--不是++
    }
    return true;

放完字符串进行判断是否回文(不用考虑有效数据i的个数为0和1的情况这些字符串都是回文)

将排好的字符串左右两边比较如果不相等就返回false如果都相等就循环结束返回true


3.翻转字符串

有个函数可以直接将字符串翻转)

reverse(初始迭代器,末迭代器)

算法头文件里#inclide里的函数reverse可直接实现反转字符,它不是vector、string里的成员函数,它还可以反转多种类型的数组(char、int...)

vector是类模板

题目是核心代码模式

c 复制代码
class Solution {
public:
    void reverseString(vector<char>& s) {
        reverse(s.begin(), s.end());
    }
};

直接调用此reverse即可

有些知识点没提是因为之前文章有讲这里就不赘述了


4.C++内存分布题目讲解

C 这里是编译时检查数据类型

B 这里是函数模板 B中的实参类型不同不符合函数模板的调用

A 、C实参类型相同 D将实参隐式类型转换为float

这里都是隐式实例化

调用模板函数显示实例化就在目标前加一个template

调用模板类显示实例化就在目标前加一个template class

template<class/typename T>(这是模板)

这里模板类是 template class Stack d(调用)

类模板是

template <class/typename T>(定义)

写一个类

D 类模板里的成员函数都是函数模板

类模板里的成员函数调用在类外定义

结构

template

返回类型 类名:: 函数名(形参...)

{

...

}

就是在目标上面加个模板,在函数名前加类名<类型名>::


文章到此就告一段落,希望对你有所帮助,感谢观看!

相关推荐
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-Nginx概述与源码编译安装
java·开发语言·nginx
lie..1 小时前
30天从零开始学AI应用开发(Day 16):Embedding 是什么?用人话讲明白“向量检索”
人工智能·算法·embedding
笨笨饿3 小时前
#141_ Codex 本地 AI 代理工具链工作流重构:Headroom、Scrapling、Archify 统一接入
开发语言·人工智能·stm32·单片机·嵌入式硬件·ui·重构
承渊政道5 小时前
星空组网+Python实战:在另一台电脑上查看CSV报表
运维·开发语言·python·csv·星空组网
Liquad Li6 小时前
Salesforce 主流认证方式、流程、适用场景
开发语言·salesforce
LOVE️YOU9 小时前
Python 中 Tuple 为什么有时可 Hash,有时不可 Hash?
开发语言·python·哈希算法
李永奉10 小时前
C语言-指针函数与函数指针及回调函数的使用
c语言·开发语言
小oo呆10 小时前
【学习心得】迭代器和可迭代对象
开发语言·python
AC赳赳老秦10 小时前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw