Напишите функцию, которая сравнивает две строки и возвращает третью строку, содержащую только буквы, которые появляются в обоих
Я получил эту домашнюю работу. И решили это следующим образом. Мне нужны ваши комментарии, будь то хороший подход или мне нужно использовать любую другую структуру данных, чтобы решить ее лучше.
public string ReturnCommon(string firstString, string scndString)
{
StringBuilder newStb = new StringBuilder();
if (firstString != null && scndString != null)
{
foreach (char ichar in firstString)
{
if (!newStb.ToString().Contains(ichar) && scndString.Contains(ichar))
newStb.Append(ichar);
}
}
return newStb.ToString();
}
Ответы
Ответ 1
Это хорошо для первого подхода, но вы можете сделать несколько улучшений, и там небольшая ошибка.
- Если
b
содержит символ в a
, который уже находится в c
, вы повторите его.
- Чтобы избежать повторений, вы можете использовать
Set
для хранения символов, так как a Set
не будет повторять.
- Сборка строк с конкатенацией
+=
обычно неэффективна; рассмотрите возможность использования StringBuilder
или аналогичного класса сборки строки.
- Имена переменных не очень описательны.
- Если
a
или b
пустые, вам не нужно вообще ничего делать! Просто верните пустую строку.
Вы также можете подумать о некоторых более сложных усовершенствованиях, представляя, как ваш алгоритм масштабируется, если вы начали использовать огромные строки. Например, один подход может заключаться в том, что если одна строка намного длиннее другой, вы можете отсортировать ее дольше и удалить дубликаты. Затем вы можете быстро выполнить двоичный поиск по символам более короткой строки.
Ответ 2
Для альтернативного решения вы можете просмотреть строки как перечисляемые и использовать Intersect()
следующим образом:
public static string Common(string first, string second)
{
return new string((first.Intersect(second)).ToArray());
}
Ответ 3
Чтобы улучшить последнее предложение Джона Фэминеллы, быстрее, чем двоичный поиск (для любой достаточно длинной строки), будет поиск в хешсе; или поиск в 256-элементном массиве логических значений, если это символы ASCII или UTF8 вместо символов UTF16.
- Создавать пустую строку hashset или пустой массив логических элементов; назовите эту переменную
found
.
- Для каждого char в первой строке либо добавьте char в hashset (но остерегайтесь дубликатов символов в первой строке),
или установите соответствующий элемент в массиве
found
равным true;
это приведет к линейному времени O (n).
- Для каждой char во второй строке проверьте, существует ли char в hashset
или соответствует ли соответствующий элемент в массиве "найденный":
если он найден, добавьте символ в возвращаемую строку, а также удалите символ
из hashset или очистить логический элемент в массиве, чтобы он больше не был найден (чтобы остерегаться дубликатов символов во второй строке); это приведет к линейному времени O (n).
Ответ 4
Кажется прекрасным. Вы можете сделать пару оптимизаций в зависимости от языка, который вы используете:
- вы можете собирать буквы b в какую-то упорядоченную структуру (чтобы быстрее ее искать), и если она не повторяется... лучше (набор).
- вы можете использовать какой-то StrignBuilder (если это Java или .Net), чтобы не воссоздавать строку с каждой конкатенацией внутри цикла
В любом случае это оптимизация, которая хороша для больших больших строк... поэтому я не знаю, является ли их апробация для вашего использования или для намеченной домашней работы.
Ответ 5
Зависит от длины входных строк, , что является буквой и как вывод должен выглядеть (дубликаты), есть несколько других подходы.
Например:
Если буквы просто [AZ] символы и каждая буква должна отображаться только один раз в выходной строке, вы может построить отдельную строку (или таблицу символов) 'ABC... XZ' (пусть назовите ее letters
) и запустите цикл for each
через letters
и проверьте обе строки ввода на каждую букву от letters
.
Этот дает 26 итераций цикла и не более, а затем 52 вызывает метода Contains()
для каждой строки ввода - независимо от того, как долго входные строки.
Ответ 6
Использование LINQ:
a.ToCharArray().Intersect<char>(b.ToCharArray())
Однако это чувствительно к регистру.
Ответ 7
FYI: Вот код C/С++:
/* Q: Write a function f(a, b) which takes two character string arguments
and returns a string containing only the characters found in both
strings in the order of a. */
#include <iostream>
#include <string>
#include <cstring>
#include <map>
using namespace std;
/* A: Unclear: repeated chars in string a? */
string CommonChars(const char* a, const char* b)
{
string result("");
if (!a || !b || !*a || !*b)
return result;
map<char, bool> hash;
int len1 = strlen(a), len2 = strlen(b);
for (int i = 0; i < len2; ++i)
hash[b[i]] = true;
for (int i = 0; i < len1; ++i)
{
map<char, bool>::iterator it = hash.find(a[i]);
if (it != hash.end() && it->second)
{
result += a[i];
hash[a[i]] = false; // OR: hash.erase(it);
}
}
return result;
}
int main()
{
cout << CommonChars("abcdefgbx", "gcfcba") << endl;
return 0;
}
/* Output:
abcfg
*/
Ответ 8
Здесь мое решение в python. Если я не ошибаюсь, это должно привести к линейному времени O (n).
# Write a function f(a, b) which takes two character string arguments
# and returns a string containing only the characters found in both
# strings in the order of a.
first_string = "attempt"
secong_string="tmay"
result = []
#it O(n) operation
for char in first_string:
if char in secong_string:
if char not in result:
result.append(char)
print result
Результаты выглядят следующим образом:
['a', 't', 'm']
Ответ 9
Похоже на меня, но для бога - человек - используйте некоторые описательные имена переменных!!