CPP——OJ试题,string、vector、类(题三)初步应用

文章目录

试题一找不重复字符、

复制代码
给定一个字符串 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++ 是自增,不是累加:你是把每个数字都加一,而不是把所有数字加起来。你需要一个单独的变量来存放总和。

相关推荐
君生我老2 小时前
C++ string类常用操作
c++
愿天堂没有C++3 小时前
C++——基础
c++
zzzsde3 小时前
【c++】深入理解string类(3):典型OJ题
开发语言·c++
青瓦梦滋3 小时前
【数据结构】哈希——位图与布隆过滤器
开发语言·数据结构·c++·哈希算法
深思慎考3 小时前
LinuxC++——etcd分布式键值存储系统入门
linux·c++·etcd
mahuifa4 小时前
C++(Qt)软件调试---Linux动态库链接异常排查(38)
linux·c++·动态库·ldd·异常排查
Juan_20124 小时前
P3051题解
c++·数学·算法·题解
深思慎考4 小时前
LinuxC++——etcd分布式键值存储系统API(libetcd-cpp-api3)下载与二次封装
linux·c++·etcd
Jiezcode5 小时前
LeetCode 138.随机链表的复制
数据结构·c++·算法·leetcode·链表