Обзор кода, C ++, метод Anagram

0

Я делаю некоторые практические вопросы из книги "Cracking the coding interview" и хотел, чтобы некоторые люди просмотрели мой код для ошибок и оптимизаций. Любая обратная связь будет принята с благодарностью.

Вопрос: Напишите метод, чтобы решить, являются ли две строки анаграммами или нет.

/*
Time complexity: O(n^2)
Space complexity: O(n)
*/
bool IsAnagram(std::string str1, std::string str2)
{
    if(str1.length() != str2.length())
        return false;
    for(int i = 0; i < str1.length();i++)
    {
        bool found = false;
        int j = 0;
        while(!found && j < str2.length())
        {
            if(str1[i] == str2[j])
            {
                found = true;
                str2[j] = NULL;
            }
            j++;
        }
        if(!found)
            return false;
    }
    return true;
}
  • 6
    Лучше подходит для codereview.stackexchange.com?
  • 3
    Вы можете получить O(n lg n) раз, если вы сортируете обе строки ...
Показать ещё 5 комментариев
Теги:
big-o
anagram
review

3 ответа

5

Это более эффективно

#include <iostream>
#include <string>
#include <algorithm>

bool IsAnagram(std::string& str1, std::string& str2)
{
  if(str1.length() != str2.length())
    return false;

  std::sort(str1.begin(), str1.end());
  std::sort(str2.begin(), str2.end());

  return str1.compare(str2) == 0;
}

int main(int argc, char* argv[])
{
  std::string an1("army");
  std::string an2("mary");
  if(IsAnagram(an1, an2)) 
    std::cout << "Hooray!\n";

    return 0;
}

Для тех, кто не любит мутирующие строки, возможно, это лучший вариант. Можно либо удалить ссылку на параметры 1 и 2, либо сделать копию внутри функции, как здесь. Таким образом, параметры могут быть const.

bool IsAnagram2(const std::string& str1, const std::string& str2)
{
   if(str1.length() != str2.length())
      return false;

   std::string cpy1(str1), cpy2(str2);

   std::sort(cpy1.begin(), cpy1.end());
   std::sort(cpy2.begin(), cpy2.end());

   return cpy1.compare(cpy2) == 0;
}
  • 2
    Это изменяет строки, которые вы передаете в функцию. Этого нельзя ожидать!
  • 0
    Лучше не сбрасывать со счетов ваши аргументы ... так что я бы снял их и позволил IsAnagram работать из локальной копии. Но все же: это прекрасное решение.
3

O(n). Вместо сортировки (это O(n lg n)), подсчитайте появления символов в s1 и сравните его с символьными вхождениями в s2.

#include <string>
#include <iostream>
#include <limits>

bool IsAnagram(const std::string& s1, const std::string& s2)
{
  if (s1.size() != s2.size()) {
    return false;
  }
  int count[std::numeric_limits<char>::max() + (std::size_t)1] = {};
  for (auto c : s1) {
    count[c]++;
  }
  for (auto c : s2) {
    if (!count[c]) {
      return false;
    }
    count[c]--;
  }
  return true;
}

int main(int argc, char **argv)
{
  std::cout << IsAnagram(argv[1], argv[2]) << std::endl;
  return 0;
}
  • 0
    +1, очень мило. Разве это технически не должно быть ..::max() + (std::size_t)1 ? (С другой стороны, я предполагаю, что все эти ответы предполагают ASCII в любом случае - анаграммы Unicode, закодированные в байтовые строки, гораздо менее забавны.) И это может быть хорошей идеей выделить его из стека, если есть платформа с широкий char и маленький стек.
  • 0
    @Cameron - я исправил проблему +1 . Благодарю. Я понимаю, что распределение стека может быть проблемой на некоторых платформах, но я все же предпочитаю его для стандартного алгоритма или алгоритма по умолчанию.
1

Существует уже стандартный алгоритм std::is_permutation который позволяет выполнять задачу просто

#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>


int main() 
{

    std::string s( "aab" );
    std::string t( "aba" );

    std::cout << std::boolalpha 
              << ( s.size() == t.size() && 
                   std::is_permutation( s.begin(), s.end(), t.begin() ) )
              << std::endl;
    return 0;
}

Выход

true

Таким образом, все потребности ypu - это увидеть, как реализуется алгоритм. :)

Если вам нужна отдельная функция, она будет выглядеть

bool IsAnagram( const std::string &s1, const std::string &s2 )
{
    return s1.size() == s2.size() &&
           std::is_permutation( s1.begin(), s1.end(), s2.begin() );
}         

Использовать std::sort не подходит, потому что исходные строки будут изменены или вам нужно передать их функции по значению.

  • 0
    Хорошее мышление, но вы должны упомянуть, что нужен достаточно современный компилятор - is_permutation - C ++ 11
  • 0
    Использовать стандартную библиотеку приятно, но учтите, что is_permutation может быть до O (n ^ 2). Пользовательский алгоритм может быть быстрее.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню