Odwracanie stringa — Zadanie rekrutacyjne #10

Czego szuka rekruter: kilka podejść, null handling, świadomość Unicode (surrogat pairs)
Poziom: Junior
Zadanie
Napisz funkcję, która odwraca string. Wejście: "Hello" → wyjście: "olleH".
Czego szuka rekruter
Odwracanie stringa to zadanie testujące znajomość kilku podejść i świadomość edge cases. Rekruter oczekuje:
- Co najmniej dwóch podejść (pętla lub
Array.Reverse) - Obsługi
nulli pustego stringa - Bonus: wiedzy o tym, że proste odwracanie tablicy charów nie działa dla emoji i znaków Unicode poza BMP
Edge cases
null→ zwróćnulllub rzućArgumentNullException""→ zwróć""- Jeden znak → zwróć ten sam znak
- String z emoji/znakami poza BMP → prosta odwrócona tablica charów da błędny wynik (patrz sekcja Unicode)
✅ Rozwiązanie 1 — Array.Reverse
static string? Reverse(string? text)
{
if (text is null) return null;
if (text.Length <= 1) return text;
char[] chars = text.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
Array.Reverse działa in-place na tablicy — O(n) czas, O(n) pamięć na tablicę charów.
✅ Rozwiązanie 2 — pętla z dwoma wskaźnikami
static string? ReverseTwoPointers(string? text)
{
if (text is null) return null;
char[] chars = text.ToCharArray();
int left = 0, right = chars.Length - 1;
while (left < right)
{
(chars[left], chars[right]) = (chars[right], chars[left]);
left++;
right--;
}
return new string(chars);
}
✅ Rozwiązanie 3 — LINQ
static string? ReverseLinq(string? text)
=> text is null ? null : new string(text.Reverse().ToArray());
Czytelne, ale mniej wydajne — Enumerable.Reverse buforuje całą sekwencję.
Pułapka Unicode — surrogat pairs i emoji
string emoji = "Hello 🎉";
char[] chars = emoji.ToCharArray();
Array.Reverse(chars);
Console.WriteLine(new string(chars)); // "?? olleH" — emoji rozbite!
Emoji 🎉 to w UTF-16 dwie wartości char (surrogate pair): 🎉. Odwrócenie tablicy char[] rozdziela je. Poprawne odwracanie dla pełnego Unicode:
using System.Globalization;
static string ReverseUnicode(string text)
{
if (string.IsNullOrEmpty(text)) return text ?? string.Empty;
// TextElementEnumerator traktuje surrogate pairs i łączniki jako jedną jednostkę
var enumerator = StringInfo.GetTextElementEnumerator(text);
var elements = new List<string>();
while (enumerator.MoveNext())
elements.Add((string)enumerator.Current);
elements.Reverse();
return string.Concat(elements);
}
Console.WriteLine(ReverseUnicode("Hello 🎉")); // "🎉 olleH" — poprawnie!
Testy jednostkowe
[Theory]
[InlineData("Hello", "olleH")]
[InlineData("a", "a")]
[InlineData("", "")]
[InlineData("abcde", "edcba")]
public void Reverse_ReturnsReversedString(string input, string expected)
{
Assert.Equal(expected, Reverse(input));
}
[Fact]
public void Reverse_Null_ReturnsNull()
{
Assert.Null(Reverse(null));
}
[Fact]
public void ReverseUnicode_WithEmoji_PreservesEmoji()
{
Assert.Equal("🎉 olleH", ReverseUnicode("Hello 🎉"));
}
Co powiedzieć na rozmowie
“Proste odwrócenie tablicy charów działa dla podstawowych znaków ASCII. Ale string w .NET to sekwencja char (UTF-16), a znaki spoza Basic Multilingual Plane — emoji, niektóre znaki chińskie — są zakodowane jako surrogate pairs (dwa char). Odwrócenie tablicy rozbija te pary. StringInfo.GetTextElementEnumerator traktuje surrogate pair jako jeden element.”
Podsumowanie
Dla ASCII i większości typowych stringów Array.Reverse na char[] jest w porządku. Na rozmowie warto wspomnieć o pułapce Unicode — to odróżnia kandydata od kogoś kto zna tylko podstawowe rozwiązanie.
Zamień wiedzę w umiejętności
Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.
Pobieram roadmapę →