No, that's not the problem. Internally the StringBuffer.reverse method uses a loop too.
The last one is inefficient because
s = s + normal.charAt(i)
doesn't append the character to s (as you probably think) but instead creates a new string object that it the concatenation of s and the character. The code is basically translated by the compiler to
s = new StringBuffer().append(s).append(normal.charAt(i)).toString()
which means you create a new StringBuffer and String object every loop iteration!
This is terribly inefficient.