文章目录
试题一找不重复字符、
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。
示例 1:
输入: s = "leetcode"
输出: 0
示例 2:
输入: s = "loveleetcode"
输出: 2
示例 3:
输入: s = "aabb"
输出: -1
提示:
1 <= s.length <= 105
s 只包含小写字母
cpp
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int fist_once(string& s)
{
vector <int>v1(26, 0);//创建26个0的动态数组
for (auto ch : s)
{
v1[ch - 'a']++;
}
int len = s.size(); //strlen是C语言中计算字符串/0前面的字符个数,而vector他不是这样的数据
//for (auto i :len)错误,auto只能用于vector、string、数组(即必须要有iterator迭代器)
//len 是一个整数,它是不可迭代对象。
for (int i = 0; i < len; i++)
{
//v1[i]==1
//判断有多少个出有出现一次的数据
if (v1[s[i] - 'a'] == 1)
//s[i] - 'a' 判断存放在v1里面相对应的字母是否出现一次
return i;
}
return -1;
}
int main()
{
while (1)
{
string s;
cin >> s;
int if_once = fist_once(s);
cout << if_once << endl;
}
return 0;
}
变式
变式题目:字符串中最后一个唯一字符
给定一个字符串 s,找到它的最后一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
示例 1:输入:s = "leetcode"输出:7(字符 'd' 是最后一个只出现一次的字符,索引为 7)
示例 2:输入:s = "loveleetcode"输出:11(字符 'd' 是最后一个只出现一次的字符,索引为 11)
示例 3:输入:s = "aabb"输出:-1
cpp
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//头文件、命名空间
int last_word_index(string& s)
{
vector<int>v1(26, 0);
int len = s.size(); //cin>>s与strlen(s);不能同时联用
for (int i = 0; i < len; i++)
{
v1[s[i] - 'a']++;//s[i]-a对应 再26个字母表中的位置
}
//判断是否有1的情况
for (int i = len - 1; i >= 0; i--)
{
if (v1[s[i] - 'a'] == 1)//s[i]-'a' 倒着对应 s每个字母再26位中的位置
{
return i;
}
else
{
return -1;
}
}
}
int main()
{
string s;
cin >> s;
int if_once = last_word_index(s);
cout << if_once << endl;
return 0;
}
知识点补充-strlen
strlen 不能和 cin>>s 中的s联用
strlen(s)计算的是 const char* str 中 str/0前面字符的个数,而cin>>s中的s,并不是const char* 类型 因此不可以联用
试题二输入单词长度、
描述
对于给定的若干个单词组成的句子,每个单词均由大小写字母混合构成,单词间使用单个空格分隔。输出最后一个单词的长度。
输入描述:
在一行上输入若干个字符串,每个字符串代表一个单词,组成给定的句子。
除此之外,保证每个单词非空,由大小写字母混合构成,且总字符长度不超过 10^3
输出描述:
在一行上输出一个整数,代表最后一个单词的长度。

cpp
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//头文件、命名空间
int last_word_len(string& s,char ch)
{
int pos = s.find_last_of(ch);
if (pos == string::npos)
{
return s.size() ;
}
else
{
pos += 1;
int len = 0;
while (pos != s.size())
{
len++;
pos++;
}
return len;
}
}
int main()
{
string s;
getline(cin,s);
/*
getline的用法
1.遇到' '不会自动结束
2.遇到\n会结束,但是cin中如果不手动输入 s中是没有\n的!!!
3.getline 可以识别' ' 但是流插入流提取,和C语言中的scanf是不会识别' '的!
*/
char ch = ' ';
int n = last_word_len(s,ch);
cout << n << endl;
return 0;
}
变式
变式题目:统计句子中每个单词的长度
题目描述:编写一个程序,读取一整行英文句子(包含空格)。程序需要将句子中的每个单词提取出来,计算每个单词的长度,并将这些长度存储在一个动态数组(vector)中。最后,打印出这个长度数组。
示例:
输入: I love C++ programming
输出: 1 4 3 11
解释:单词 "I" 长度为 1, "love" 长度为 4, "C++" 长度为 3, "programming" 长度为 11
cpp
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//头文件、命名空间
int main()
{
string str;
getline(cin,str);
//int len_str = str.size();
//int num_space = 0;
//for (int index = 0; index < len_str; index++)
//{
// if (str[index] == ' ')
// num_space++;
//}
//int num_word = num_space+1; //错误写法 int num_word = num_space++
vector<int>v1;
int beg = 0;
int current_len = 0;
while (beg != str.size())
{
if (str[beg] != ' ')
{
current_len++;
}
else
{
v1.push_back(current_len);
current_len = 0;
}
beg++;
}
v1.push_back(current_len);
for (auto x : v1)
{
cout << x << " ";
}
return 0;
}
知识点补充-getline
getline的用法
1.遇到' '不会自动结束
getline 可以识别' ' 但是流插入流提取,和C语言中的scanf是不会识别' '的,遇到' '就认为已经结束了!
ex:一个特例:如果在getline前使用了cin >> x(比如cin >> a; getline(cin, s);),cin >>会读取数据但留下\n在输入流中。此时getline会直接读取到这个\n,导致s为空
cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
int age;
string name;
cout << "请输入你的年龄:";
cin >> age; // 假设输入:20[回车]
cout << "请输入你的名字:";
getline(cin, name); // 这里会出问题
cout << "你的年龄是" << age << ",名字是" << name << endl;
return 0;
}

2.遇到\n会结束,但是如果不手动输入\n 他是不会再字符串中自动留一个\n的
ex:
string s;cin>>s; 这里输入完s之后默认最后有一个\n。
strings;getline(cin,s) 这里输入完之后,最后没有\n。
再循环遍历条件中一定要注意后缀++/--或者前缀++/--,这里很容易出错,在上述条件中,若使用后缀++,将会出现错误结果。这种情况可以采用赋值方法避免
试题三回文字符串、

cpp
#include<iostream>
#include<string>
#include<vector>
#include<cctype>
using namespace std;
//头文件、命名空间
int main()
{
string str;
getline(cin, str);
string s;
for (auto ch : str)
{
if (isalnum(ch))
{
s += tolower(ch); //tolower 是一个函数,函数是有返回值的
}
}
//int len = str.size();
//for (int i = 0; i < str.size(); i++)
//{
// if (str[i] != ' ')
// {
// if (isupper(str[i]))
// {
// tolower(str[i]);
// }
// s += str[i];
// }
//}
bool ishuiwen = true;
int beg = 0;
int end = s.size() - 1;
while (beg <= end)
{
if (s[beg] == s[end])
{
beg++;
end--;
}
else
{
ishuiwen = false;
break;
}
}
if (ishuiwen) {
cout << "是回文" << endl;
}
else {
cout << "不是回文" << endl;
}
return 0;
}
变式
cpp
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
// 回文子串收集器类,封装所有功能
class PalindromeCollector {
private:
// 辅助函数:判断字符串是否为回文(仅字母数字,忽略大小写)
bool isPalindrome(const string& s) {
int left = 0; // 左指针,从子串开头开始
int right = s.size() - 1; // 右指针,从子串结尾开始
while (left < right) { // 当左指针小于右指针时,继续比较
// 统一转小写后比较字符
if (tolower(s[left]) != tolower(s[right])) {
return false; // 字符不相等,不是回文
}
left++; // 左指针右移
right--; // 右指针左移
}
return true; // 所有字符对都相等,是回文
}
// 辅助函数:过滤非字母数字字符,只保留字母和数字
string filterNonAlnum(const string& s) {
string res;
for (char ch : s) {
if (isalnum(ch)) { // 判断是否为字母或数字
res += ch; // 是则保留
}
}
return res;
}
public:
// 核心函数:收集所有长度≥2的回文子串
vector<string> collect(const string& input) {
vector<string> result; // 存储结果的vector
string filtered = filterNonAlnum(input); // 先过滤非字母数字字符
int n = filtered.size(); // 过滤后的字符串长度
// 枚举所有可能的子串(i是子串起始位置,j是子串结束位置)
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) { // j从i+1开始,保证子串长度≥2
string sub = filtered.substr(i, j - i + 1); // 截取子串
if (isPalindrome(sub)) { // 判断子串是否为回文
result.push_back(sub); // 是则加入结果vector
}
}
}
return result;
}
// 打印收集到的回文子串,格式如["a","b"]
void printResult(const vector<string>& v) {
cout << "[";
for (size_t i = 0; i < v.size(); i++) {
cout << "\"" << v[i] << "\""; // 打印带双引号的子串
if (i != v.size() - 1) {
cout << ", "; // 除最后一个外,加逗号分隔
}
}
cout << "]" << endl;
}
};
int main() {
string input;
getline(cin, input); // 读取整行输入(包含空格)
PalindromeCollector collector; // 实例化收集器对象
vector<string> palindromes = collector.collect(input); // 收集回文子串
collector.printResult(palindromes); // 打印结果
return 0;
}
知识点补充-cctype
isupper islower toupper tolower都是cctype里面的函数他们都是一个返回值,所以需要用变量来接收返回值。而不是直接调用。
试题四反转字符串(无变式)、

cpp
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//头文件、命名空间
int main()
{
string str;
getline(cin, str);
int beg = 0;
int end = str.size() - 1;
while (beg < end)
{
swap(str[beg], str[end]);
beg++;
end--;
}
cout << str << endl;
return 0;
}
试题五自实现atoi、
cpp
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int my_atoi(string& s)
{
int i = 0;
int fu = 1;
//除去空格
while(i<s.size())
{
if (s[i] == ' ')
{
i++;
}
else if (i < s.size() &&(s[i] == '+' || s[i] == '-'))
{
//判断正负
{
fu = (s[i]=='-' ? -1 : 1);
i++;
break;
}
}
break;
}
int result = 0;
while (i < s.size()&&isdigit(s[i]))
{
int num = s[i] - '0';
result = result * 10 + num;
i++;
}
return fu * result;
}
int main()
{
string s;
cin >> s;
int res = my_atoi(s);
cout << res << endl;
return 0;
}
变式
cpp
#include<iostream>
#include<string>
#include<vector>
#include<cctype>
using namespace std;
int s_num_sum(string& s)
{
int id = 0;
int result = 0;
vector<int>v1;
while (id < s.size())
{
if (isdigit(s[id]))
{
result = result * 10 + (s[id] - '0');
}
else if(result !=0)
{
v1.push_back(result);
result = 0;
}
id++;
}
if (result != 0)
{
v1.push_back(result);
}
int sum = 0;
for (auto num : v1)
{
if (num != 0)
{
sum += num;
}
}
return sum;
}
int main()
{
string s;
getline(cin, s);
int res = s_num_sum(s);
cout << res << endl;
return 0;
}
补充-auto临时拷贝
(auto num : v1)
{
if (num != 0)
{
num++; // 错误在这里!
}
这行代码有两个问题:
auto num 是值传递:你在这里修改的 num 只是一个临时副本,它的改变不会影响 vector 中存储的原始值。
num++ 是自增,不是累加:你是把每个数字都加一,而不是把所有数字加起来。你需要一个单独的变量来存放总和。