ReverseString, вопрос интервью C#

Если кто-то еще ищет ответ, он может использовать функцию уведомления об изменении базы данных Oracle , поставляемую с Oracle 10g. Требуется CHANGE NOTIFICATION системная привилегия. Вы можете зарегистрировать слушателей, когда вызывать уведомление обратно в приложение.

10
задан 4 revs, 2 users 95%user34537 17 June 2009 в 22:06
поделиться

7 ответов

Несколько комментариев к уже полученным ответам:

  • Каждый из них (пока!) Не работает с суррогатными парами и комбинирующими символами. О радостях Unicode. Перевернуть строку - это не то же самое, что перевернуть последовательность символов.
  • Мне нравится оптимизация Марка для пустых, пустых и одиночных символов. В частности, это не только быстро дает правильный ответ, но и обрабатывает null (чего не делает ни один из других ответов)
  • Первоначально я думал, что ToCharArray , за которым следует Array.Reverse будет самым быстрым, но он создает одну «мусорную» копию.
  • Решение StringBuilder создает одну строку (не массив символов) и манипулирует ею, пока вы не вызовете ToString ]. Никакого дополнительного копирования не требуется ... но есть еще много работы по поддержанию длины и т. д.

Какое решение более эффективное? Что ж, мне пришлось бы протестировать его, чтобы иметь хоть какое-то представление, но даже в этом случае это не расскажет всей истории. Вы используете это в ситуации с высоким давлением памяти, когда лишний мусор - настоящая боль? Насколько быстро ваша память по сравнению с вашим процессором и т. Д.?

Как всегда, читаемость обычно король - и в этом вопросе нет ничего лучше, чем ответ Марка. В частности, нет места для единичной ошибки, тогда как мне действительно пришлось бы подумать, чтобы проверить другие ответы. Я не люблю думать. У меня болит мозг, поэтому я стараюсь не делать это очень часто. Использование встроенного Array.Reverse кажется мне намного лучше. (Хорошо, значит, он все еще не работает с суррогатами и т. Д.,

21
ответ дан 3 December 2019 в 13:09
поделиться

Самое главное? Это отстой с точки зрения производительности - он должен создать много строк (по одной на символ). Самый простой способ выглядит примерно так:

public static string Reverse(string sz) // ideal for an extension method
{
    if (string.IsNullOrEmpty(sz) || sz.Length == 1) return sz;
    char[] chars = sz.ToCharArray();
    Array.Reverse(chars);
    return new string(chars);
}
57
ответ дан 3 December 2019 в 13:09
поделиться

Проблема в том, что конкатенация строк требует больших затрат, поскольку строки неизменяемы в C #. В приведенном примере на каждой итерации будет создаваться новая строка на один символ длиннее, что очень неэффективно. Чтобы избежать этого, вы должны использовать класс StringBuilder , например:

public string ReverseString(string sz)
{
    var builder = new StringBuilder(sz.Length);
    for(int i = sz.Length-1; i>=0; i--)
    {
      builder.Append(sz[i]);
    }
    return builder.ToString();
}

StringBuilder написан специально для подобных сценариев, поскольку он дает вам возможность объединять строки без недостатка чрезмерного выделения памяти.

Вы заметите, что я предоставил StringBuilder начальную емкость, которую вы редко видеть. Как вы знаете длину результата для начала, это удаляет ненужное выделение памяти.

Обычно происходит то, что он выделяет объем памяти для StringBuilder (по умолчанию 16 символов). Как только содержимое пытается превысить эту емкость, оно удваивает (я думаю) свою емкость и продолжает работать. Это намного лучше, чем выделять память каждый раз, как это происходит с обычными строками, но если вы можете этого избежать, это даже лучше.

Вы заметите, что я предоставил StringBuilder начальную емкость, которую вы не часто видите. Как вы знаете длину результата для начала, это удаляет ненужное выделение памяти.

Обычно происходит то, что он выделяет объем памяти для StringBuilder (по умолчанию 16 символов). Как только содержимое пытается превысить эту емкость, оно удваивает (я думаю) свою емкость и продолжает работать. Это намного лучше, чем выделять память каждый раз, как это происходит с обычными строками, но если вы можете этого избежать, это даже лучше.

Вы заметите, что я предоставил StringBuilder начальную емкость, которую вы не часто видите. Как вы знаете длину результата для начала, это удаляет ненужное выделение памяти.

Обычно происходит то, что он выделяет объем памяти для StringBuilder (по умолчанию 16 символов). Как только содержимое пытается превысить эту емкость, оно удваивает (я думаю) свою емкость и продолжает работать. Это намного лучше, чем выделять память каждый раз, как это происходит с обычными строками, но если вы можете этого избежать, это даже лучше.

Как только содержимое пытается превысить эту емкость, оно удваивает (я думаю) свою емкость и продолжает работать. Это намного лучше, чем выделять память каждый раз, как это происходит с обычными строками, но если вы можете этого избежать, это даже лучше.

Как только содержимое пытается превысить эту емкость, оно удваивает (я думаю) свою емкость и продолжает работать. Это намного лучше, чем выделять память каждый раз, как это происходит с обычными строками, но если вы можете этого избежать, это даже лучше.

36
ответ дан 3 December 2019 в 13:09
поделиться

Вместо этого вы можете сделать это в .NET 3.5:

    public static string Reverse(this string s)
    {
        return new String((s.ToCharArray().Reverse()).ToArray());
    }
3
ответ дан 3 December 2019 в 13:09
поделиться

Поскольку строки неизменяемы, каждый оператор + = создает новую строку, копируя строку на последнем шаге вместе с одним символом для формирования новой строки. По сути, это будет алгоритм O (n 2 ) вместо O (n).

Более быстрый способ будет (O (n)):

// pseudocode:
static string ReverseString(string input) {
    char[] buf = new char[input.Length];
    for(int i = 0; i < buf.Length; ++i)
       buf[i] = input[input.Length - i - 1];
    return new string(buf);
}
7
ответ дан 3 December 2019 в 13:09
поделиться

Лучшим способом решения этой проблемы было бы использование StringBuilder, поскольку он не является неизменяемым, вы не получите ужасного поведения генерации объектов, которое вы получили бы выше. В .net все строки неизменяемы, а это означает, что оператор + = будет создавать новый объект при каждом ударе. StringBuilder использует внутренний буфер, поэтому обращение может быть выполнено в буфере без выделения дополнительных объектов.

1
ответ дан 3 December 2019 в 13:09
поделиться

Вы должны использовать класс StringBuilder для создания вашей результирующей строки. Строка неизменяема, поэтому, когда вы добавляете строку при каждом взаимодействии цикла, необходимо создавать новую строку, что не очень эффективно.

1
ответ дан 3 December 2019 в 13:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: