← Назад к вопросам

Как развернуть строку

2.2 Middle🔥 181 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ответ

Разворот строки (reversal) — классическая задача, которая часто встречается на интервью и в реальной разработке. Рассмотрю несколько способов от простых к оптимальным.

1. Встроенный метод (самый простой)

public class StringReversal {
    
    public static String reverse(String str) {
        return new StringBuilder(str).reverse().toString();
    }
    
    public static void main(String[] args) {
        String original = "Hello World";
        String reversed = reverse(original);
        System.out.println(reversed);  // dlroW olleH
    }
}

Это оптимально для production кода.

2. Цикл в обратном порядке

public class ManualReversal {
    
    public static String reverseWithLoop(String str) {
        String reversed = "";
        for (int i = str.length() - 1; i >= 0; i--) {
            reversed += str.charAt(i);
        }
        return reversed;
    }
    
    public static void main(String[] args) {
        String original = "Java";
        System.out.println(reverseWithLoop(original));  // avaJ
    }
}

Проблема: неэффективно! Каждый += создаёт новую String (immutable).

3. StringBuilder для оптимизации

public class OptimizedReversal {
    
    public static String reverseOptimized(String str) {
        StringBuilder sb = new StringBuilder();
        for (int i = str.length() - 1; i >= 0; i--) {
            sb.append(str.charAt(i));
        }
        return sb.toString();
    }
    
    public static void main(String[] args) {
        String original = "Development";
        System.out.println(reverseOptimized(original));  // tnempolevеD
    }
}

Лучше! StringBuilder переиспользует буфер.

4. Массив символов (самый быстрый)

public class CharArrayReversal {
    
    public static String reverseWithArray(String str) {
        char[] chars = str.toCharArray();
        
        // Two-pointer approach
        int left = 0, right = chars.length - 1;
        while (left < right) {
            // Swap
            char temp = chars[left];
            chars[left] = chars[right];
            chars[right] = temp;
            
            left++;
            right--;
        }
        
        return new String(chars);
    }
    
    public static void main(String[] args) {
        String original = "Programming";
        System.out.println(reverseWithArray(original));  // gnimmargorP
    }
}

Это оптимально по памяти и скорости.

5. Рекурсия (для интервью)

public class RecursiveReversal {
    
    public static String reverseRecursive(String str) {
        // Base case
        if (str == null || str.isEmpty()) {
            return str;
        }
        // Recursive case
        return reverseRecursive(str.substring(1)) + str.charAt(0);
    }
    
    public static void main(String[] args) {
        String original = "Recursive";
        System.out.println(reverseRecursive(original));  // evisruceR
    }
}

Не рекомендуется для production (может быть StackOverflow для больших строк).

6. Stream API (функциональный подход)

import java.util.stream.IntStream;

public class StreamReversal {
    
    public static String reverseWithStream(String str) {
        return IntStream.rangeClosed(1, str.length())
            .map(i -> str.charAt(str.length() - i))
            .collect(
                StringBuilder::new,
                (sb, c) -> sb.append((char) c),
                StringBuilder::append
            )
            .toString();
    }
    
    public static void main(String[] args) {
        String original = "Stream";
        System.out.println(reverseWithStream(original));  // maertS
    }
}

Читаемо, но не самый быстрый способ.

7. Разворот Unicode символов

public class UnicodeReversal {
    
    public static String reverseUnicode(String str) {
        // Правильно работает с многобайтными символами
        int[] codePoints = str.codePoints().toArray();
        
        // Reverse array
        for (int i = 0, j = codePoints.length - 1; i < j; i++, j--) {
            int temp = codePoints[i];
            codePoints[i] = codePoints[j];
            codePoints[j] = temp;
        }
        
        return new String(codePoints, 0, codePoints.length);
    }
    
    public static void main(String[] args) {
        String original = "Hello 世界 🌍";
        System.out.println(reverseUnicode(original));
        // 🌍 界世 olleH
    }
}

8. Разворот слов в строке

public class ReverseWords {
    
    // Развернуть слова, не символы
    public static String reverseWords(String str) {
        String[] words = str.split(" ");
        
        // Reverse words array
        for (int i = 0, j = words.length - 1; i < j; i++, j--) {
            String temp = words[i];
            words[i] = words[j];
            words[j] = temp;
        }
        
        return String.join(" ", words);
    }
    
    public static void main(String[] args) {
        String original = "The quick brown fox";
        System.out.println(reverseWords(original));
        // fox brown quick The
    }
}

9. Разворот с сохранением регистра

public class CasePreservingReversal {
    
    public static String reverseWithCasePreservation(String str) {
        char[] reversed = str.toCharArray();
        int left = 0, right = reversed.length - 1;
        
        // Развёртываем символы
        while (left < right) {
            char temp = reversed[left];
            reversed[left] = reversed[right];
            reversed[right] = temp;
            left++;
            right--;
        }
        
        // Теперь применяем original case
        char[] original = str.toCharArray();
        for (int i = 0; i < reversed.length; i++) {
            if (Character.isUpperCase(original[i])) {
                reversed[i] = Character.toUpperCase(reversed[i]);
            } else {
                reversed[i] = Character.toLowerCase(reversed[i]);
            }
        }
        
        return new String(reversed);
    }
    
    public static void main(String[] args) {
        String original = "Hello WORLD";
        System.out.println(reverseWithCasePreservation(original));
        // DLROW olleH
    }
}

10. Тесты для проверки

import static org.junit.jupiter.api.Assertions.*;

public class ReverseStringTest {
    
    @Test
    void testBasicReversal() {
        assertEquals("dlroW olleH", 
            reverse("Hello World"));
    }
    
    @Test
    void testEmptyString() {
        assertEquals("", reverse(""));
    }
    
    @Test
    void testSingleCharacter() {
        assertEquals("A", reverse("A"));
    }
    
    @Test
    void testPalindrome() {
        assertEquals("racecar", reverse("racecar"));
    }
    
    @Test
    void testWithSpecialChars() {
        assertEquals("@!#", reverse("#!@"));
    }
    
    @Test
    void testWithUnicode() {
        String emoji = "A😀B";
        String reversed = reverse(emoji);
        assertTrue(reversed.contains("😀"));
    }
    
    private String reverse(String str) {
        return new StringBuilder(str).reverse().toString();
    }
}

Сравнение производительности

public class PerformanceComparison {
    
    public static void main(String[] args) {
        String test = "a".repeat(100000);
        
        // StringBuilder.reverse()
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            new StringBuilder(test).reverse().toString();
        }
        System.out.println("StringBuilder: " + 
            (System.currentTimeMillis() - start) + "ms");
        
        // Char array
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            char[] chars = test.toCharArray();
            reverseArray(chars);
            new String(chars);
        }
        System.out.println("Char Array: " + 
            (System.currentTimeMillis() - start) + "ms");
    }
    
    private static void reverseArray(char[] chars) {
        int left = 0, right = chars.length - 1;
        while (left < right) {
            char temp = chars[left];
            chars[left] = chars[right];
            chars[right] = temp;
            left++;
            right--;
        }
    }
}

Рекомендация

СценарийМетодПричина
Production codeStringBuilder.reverse()Оптимально, читаемо
ИнтервьюTwo-pointer + arrayПоказывает понимание алгоритмов
Большие строкиStringBuilderЭффективно по памяти
Unicode stringscodePoints()Правильно для многобайтных
Функциональный стильStream APIЧитаемо для функционального

Лучший выбор для production: new StringBuilder(str).reverse().toString()

Это оптимально, безопасно и читаемо. Встроенная логика StringBuilder уже оптимизирована JVM.