我知道已经存在使用#include <algorithm>
的解决方案,但我想知道以下是否可行的方法:
#include <iostream>
using namespace std;
void remove_character_from_result(string& result, char remove){
int size = result.size();
for (int i = 0; i < size; i++){
int pos = result.find(remove);
if(pos == result.npos) break;
else{
if(pos == 0)
result = result.substr(1);
else
result = result.substr(0, pos) + result.substr(pos + 1);
}
}
}
int main() {
string result = "Asad Ahmad";
remove_character_from_result(result, 'A');
cout << result << endl;
return 0;
}
我已经针对正常的测试用例测试了我的代码,它似乎确实有效,我不确定时间复杂度是否会比result.erase(remove(result.begin(), result.end(), 'A'), result.end());
更好,如果任何人可以对此有所了解:) PS我为不使用引用而不是指针或&#39; *&#39;而道歉。而不是&#39; - &gt;&#39;早些时候 - 这是我写的代码,我并不为此感到自豪......
答案 0 :(得分:3)
您的代码有各种各样的问题。
#include <iostream>
如果您要访问std::string
课程,则需要#include <string>
。您不应该依赖<iostream>
using namespace std;
这是一种可怕的做法,使用std
中的所有名称来污染您的全局命名空间。如果您想避免重复特定名称,请选择语法
using std::string;
例如。
void remove_character_from_result(string* result, char remove){
您的代码不会检查此指针是否为空。最好通过引用来获取参数。
void remove_character_from_result(string& result, char remove){
int size = (*result).size();
虽然(*result).size()
达到了目的,但您应该使用->
来提醒自己正在使用指针,并且可能记得检查它是否为空。
size = result->size();
这里我们也遇到了程序中的错误:
int size = result->size();
size()
会返回一个std::string::size_type
,它是无符号的,可能会显着大于int
。一旦字符串大于std::numeric_limits<int>::max()
,您的代码就会停止工作。
这应该是
auto size = result->size();
或
std::string::size_type size = result->size();
for (int i = 0; i < size; i++){
我们再次遇到尺寸问题,但我们也遇到了在操作过程中尺寸可能会发生变化的问题。您应该用以下代码替换这两行:
for (std::string::size_type i = 0; i < result->size(); ++i) {
下一段代码:
int pos = (*result).find(remove);
if(pos == (*result).npos) break;
else{
if(pos == 0)
*result = (*result).substr(1);
else
*result = (*result).substr(0, pos) + (*result).substr(pos + 1);
没有多大意义,并且做事很难。在第一种情况下,您创建一个新的子字符串,然后将其复制到您自己。在第二种情况下,您创建两个临时子串,您将它们一起添加到第三个,然后将其复制到自己。
最好使用erase
。
还不清楚为什么你首先要有尺寸约束的循环。
你最好用这样的东西替换整个函数:
#include <iostream>
#include <string>
void remove_character_from_result(std::string& result, char remove) {
for (size_t pos = 0; (pos = result.find(remove, pos)) != result.npos; ) {
size_t end = pos + 1;
while (end < result.size() && result[end] == remove)
++end;
result.erase(pos, end - pos);
}
}
int main() {
std::string s = "hello world";
remove_character_from_result(s, 'l');
std::cout << s << '\n';
}
最坏情况下的时间复杂度是它必须删除一半的字符,即O(NlogN)。
您可以通过从右侧而不是左侧进行操作来提高性能:考虑从“ababab”中删除字符“a”。第一次擦除之后是复制5个字符,第二个擦除3个字符,第三个擦除1个字符。如果我们以相反的方式工作,第一个擦除将是1个字符,第二个擦除2和第三个擦除3。
答案 1 :(得分:0)
如果您真的坚持自己这样做,您可能希望使用string
的成员函数进行搜索。对于(可能微小的)效率增益,您还希望从结束回到字符串的开头进行搜索。我也会通过引用传递字符串而不是传递指针。
最后,您不必用子串创建一个新字符串,也可以删除想要删除的字符:
void remove_character(string &result, char remove) {
std::string::size_type pos;
while ((pos = result.rfind(remove)) != std::string::npos)
result.erase(pos, 1);
}
如果您想要优化一点(或可能甚至更多),您可以从找到上一个实例的点恢复第二次和后续搜索:
void remove_character(string &result, char remove) {
std::string::size_type pos = std::string::npos;
while ((pos = result.rfind(remove, pos)) != std::string::npos)
result.erase(pos, 1);
}