Два указателя
Два индекса вместо лишних проходов
Техника двух указателей работает со строками так же естественно, как с массивами. Один индекс может начинаться слева, другой — справа, а на каждом шаге алгоритм решает, какой из них нужно сдвинуть дальше.
Поскольку String неизменяем, для простой проверки достаточно двигать индексы по исходной строке.
Если же символы нужно переставлять, строку можно временно представить как char[].
Движение навстречу
Например, строку можно развернуть, меняя местами симметричные позиции. Каждая пара обрабатывается один раз.
char[] chars = text.toCharArray();
int left = 0;
int right = chars.length - 1;
while (left < right) {
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right--;
}
String reversed = new String(chars);
Левый указатель двигается вправо, правый — влево, поэтому цикл выполняет примерно половину длины строки итераций.
Временная сложность остаётся O(n).
Дополнительный массив здесь нужен из-за неизменяемости String, а сама логика указателей использует O(1) дополнительной памяти.
Указатели не обязаны двигаться одинаково
В более интересных задачах один указатель может задерживаться, пока второй ищет подходящий символ, или один из них может пропускать позиции, которые не участвуют в сравнении. Главная идея не в симметричном движении, а в том, что каждый индекс имеет понятную роль и не возвращается назад без необходимости.
left — первая ещё не обработанная позиция слева»,
а «right — первая ещё не обработанная позиция справа».
Тогда условие цикла и моменты сдвига становятся гораздо понятнее.