Reverse String

medium

By - Aman Pareek

Last Updated - 02/09/2024

Problem Statement

You are given an array of characters s that represents a string. Your task is to reverse the characters in the array in-place. This means you need to modify the original array directly, without using extra memory for another array. The goal is to reverse the string efficiently using O(1) extra space.

Example 1

Input: s = ["h","e","l","l","o"]

Output: ["o","l","l","e","h"]

Example 2

Input: array = ["H","a","n","n","a","h"]

Output: ["h","a","n","n","a","H"]

Solution 1: Two-Pointer Technique

function reverseStringTwoPointer(s) {
    let left = 0;
    let right = s.length - 1;
    while (left < right) {
        [s[left], s[right]] = [s[right], s[left]];
        left++;
        right--;
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringTwoPointer(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringTwoPointer(array2);  //output: ["h","a","n","n","a","H"] 

Solution 2: Iterative Approach

function reverseStringIterative(s) {
    const length = s.length;
    for (let i = 0; i < Math.floor(length / 2); i++) {
        const temp = s[i];
        s[i] = s[length - 1 - i];
        s[length - 1 - i] = temp;
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringIterative(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringIterative(array2);  //output: ["h","a","n","n","a","H"] 

Solution 3: Using JavaScript Array.prototype.reverse()

function reverseStringArrayReverse(s) {
    s.reverse();
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringArrayReverse(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringArrayReverse(array2);  //output: ["h","a","n","n","a","H"] 

Solution 4: Stack-Based Approach

function reverseStringStack(s) {
    const stack = [];
    s.forEach(char => stack.push(char));
    for (let i = 0; i < s.length; i++) {
        s[i] = stack.pop();
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringStack(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringStack(array2);  //output: ["h","a","n","n","a","H"] 

Solution 5: Recursive Approach

function reverseStringRecursive(s) {
    function helper(left, right) {
        if (left >= right) return;
        [s[left], s[right]] = [s[right], s[left]];
        helper(left + 1, right - 1);
    }
    helper(0, s.length - 1);
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringRecursive(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringRecursive(array2);  //output: ["h","a","n","n","a","H"] 

Solution 6: Using In-Place Swap with Helper Function

function reverseStringInPlace(s) {
    const swap = (i, j) => {
        const temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    };

    let left = 0;
    let right = s.length - 1;
    while (left < right) {
        swap(left, right);
        left++;
        right--;
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringInPlace(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringInPlace(array2);  //output: ["h","a","n","n","a","H"] 

Solution 7: Using Bitwise XOR for Swap

function reverseStringXOR(s) {
    let left = 0;
    let right = s.length - 1;
    while (left < right) {
        // Swap elements using XOR
        s[left] = String.fromCharCode(s[left].charCodeAt(0) ^ s[right].charCodeAt(0));
        s[right] = String.fromCharCode(s[left].charCodeAt(0) ^ s[right].charCodeAt(0));
        s[left] = String.fromCharCode(s[left].charCodeAt(0) ^ s[right].charCodeAt(0));
        
        left++;
        right--;
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringXOR(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringXOR(array2);  //output: ["h","a","n","n","a","H"] 

Solution 8: Using Deques (Double-ended Queue)

function reverseStringDeque(s) {
    const deque = [];
    for (const char of s) {
        deque.push(char);
    }
    for (let i = 0; i < s.length; i++) {
        s[i] = deque.pop();
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringDeque(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringDeque(array2);  //output: ["h","a","n","n","a","H"] 

Solution 9: Using Two Arrays (Intermediate Storage)

function reverseStringTwoArrays(s) {
    const reversed = [];
    for (let i = s.length - 1; i >= 0; i--) {
        reversed.push(s[i]);
    }
    for (let i = 0; i < s.length; i++) {
        s[i] = reversed[i];
    }
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringTwoArrays(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringTwoArrays(array2);  //output: ["h","a","n","n","a","H"] 

Solution 10: Using Built-In Methods with Spread Operator

function reverseStringSpread(s) {
    s.splice(0, s.length, ...s.reverse());
    return s;
} 

const s1 = ["h","e","l","l","o"];
reverseStringSpread(s1);  //output: ["o","l","l","e","h"] 

const array2 = ["H","a","n","n","a","h"];
reverseStringSpread(array2);  //output: ["h","a","n","n","a","H"]