Недавно я был в техническом интервью на С++, где мне был предоставлен немного простой код манипуляции строкой, который предназначен для ввода строки и возврата строки, состоящей из первого и последнего n-символов, а затем продолжения чтобы исправить любые ошибки, а также сделать функцию максимально эффективной, я придумал решение ниже, однако интервьюер утверждал, что существует еще более оптимальный способ:
Исходный код:
std::string first_last_n(int n, std::string s)
{
std::string first_n = s.substr(0,n);
std::string last_n = s.substr(s.size()-n-1,n);
return first_n + last_n;
}
Мой код:
bool first_last_n(const std::size_t& n, const std::string& s, std::string& r)
{
if (s.size() < n)
return false;
r.reserve(2 * n);
r.resize(0);
r.append(s.data(),s.data() + n);
r.append(s.data() + (s.size() - n), s.data() + s.size());
return true;
}
Резюме моих изменений:
-
Изменен интерфейс, чтобы взять возвращаемую строку в качестве ссылки (если RVO и rvalues еще не доступны)
-
Удалены временные строки, построенные с помощью substr
-
Пропустил входную строку в качестве ссылки const для того, чтобы обойти временную инстанцировку ввода
-
Исправлена ошибка "за один" в строке last_n
-
Уменьшено количество раз, когда каждый символ коснулся один или два раза (в случае перекрывающегося сценария)
-
Размещена проверка в случае, если размер строки s меньше n, возвращая false для отказа.
Предполагая, что разрешен только собственный С++, есть ли другой способ сделать это более эффективно или оптимально?
Примечание 1: Исходный экземпляр исходной строки не должен быть изменен.
Примечание 2: Все решения должны проходить следующий тестовый пример, иначе они недействительны.
void test()
{
{
std::string s = "0123456789";
std::string r = first_last_n(10,s);
assert(r == "01234567890123456789");
}
{
std::string s = "0123456789ABC0123456789";
std::string r = first_last_n(10,s);
assert(r == "01234567890123456789");
}
{
std::string s = "1234321";
std::string r = first_last_n(5,s);
assert(r == "1234334321");
}
}