Если вы не хотите использовать какую-либо встроенную функцию, вам нужно вернуться со строкой к ее составным частям: массиву символов.
Теперь возникает вопрос, какой самый эффективный способ инвертировать массив? Ответ на этот вопрос на практике также зависит от использования памяти (для очень больших строк), но в теории эффективность в этих случаях измеряется при доступе к массиву.
Самый простой способ - создать новый массив и заполнить его значениями, с которыми вы столкнетесь при обратной итерации по исходному массиву и возвращении нового массива. (Хотя с временной переменной вы также можете сделать это без дополнительного массива, как в ответе Саймона Никерсона).
Таким образом, вы получаете доступ к каждому элементу ровно один раз для массива с n элементами. Таким образом, давая эффективность O (n).