loading...
Cover image for Interview Qs Decoded - # 2

Interview Qs Decoded - # 2

catcarbn profile image Cat Carbonell ・2 min read

I wanted to share with you all an actual challenge I was given during an interview!

The interviewer said, "Alright, let's do some string reversals!"

I responded with this exact face:
A very excited girl


The Q: Write a function that accepts a string as a single argument, and when called, reverses the string.

Restrictions:

  • You cannot use .reverse() or .reduce()!

Edge Cases:

  • Punctuation does not matter
  • Disregard numbers, we are only looking at strings

Given Argument:

const string="Reverse me!";
Enter fullscreen mode Exit fullscreen mode

Setup:

function revFunction(str){
};
Enter fullscreen mode Exit fullscreen mode

I asked the interviewer if I could use .split(), and he said, "sure, go ahead."

Protip: Always ask questions!!

function revFunction(str){
   const splitString =  str.split('');
};
Enter fullscreen mode Exit fullscreen mode

What .split() does is separate each character into individual indexes, making it into an array. I set it as a const variable splitString so I could call on it later.

Next, I thought of iterating through this new array, and so I utilized a classic for-loop

function revFunction(str){
   const splitString =  str.split('');
   for(let i = 0; i <= str.length; i++){}
};
Enter fullscreen mode Exit fullscreen mode

Now, what do I do when iterating through str? Yes, I need to go through them individually, but I need to iterate the other way. I asked if I could use .pop() since pop removes the last item in an array. He gave me the go-ahead.

function revFunction(str){
   const splitString =  str.split('');
   for(let i = 0; i <= str.length; i++){
      // --------
      splitString.pop();
      // --------
   }
};
Enter fullscreen mode Exit fullscreen mode

But we need that last letter! We can't just send it into the abyss! My solution to hold the popped item was to .push() it into a new, empty array.

function revFunction(str){
   const splitString =  str.split('');
   // --------
   const reversedString = [];
   // --------
   for(let i = 0; i <= str.length; i++){
      // --------
       reversedString.push(splitString.pop());
      // --------
   }
};
Enter fullscreen mode Exit fullscreen mode

At this point, if we console.log the revFunction, it will return as an array.

// [!,e,m, ,e,s,r,e,v,e,R]
Enter fullscreen mode Exit fullscreen mode

Success!

But, the interviewer wanted the function to return a solid string. I asked if I could use .join(). He approved.

function revFunction(str){
   const splitString =  str.split('');
   const reversedString = [];
   for(let i = 0; i <= str.length; i++){
       reversedString.push(splitString.pop());
   }
   // ---- //
   return reversedString.join('');
   // ---- //
};
Enter fullscreen mode Exit fullscreen mode

This should return:

//!em esreveR
Enter fullscreen mode Exit fullscreen mode

We did it! There are many ways to reverse a string without the .reverse() method. What I covered was the iterative way (iterating with a for-loop).

I challenge you to solve this challenge (in your language of choice) in the comments!


Try it out on my Repl!


Thanks for reading!!

Got a beginner-level interview question for me? DM me on Twitter! I'm always up for challenges!

Discussion

pic
Editor guide
Collapse
arthurabia profile image
Arty ‽

Nice use of pop()!
I would not have think of that...
Here's how I went about it :

let str = 'please reverse me';
let newStr = '' ;
for(let i= str.length -1;i >=0;i--){
newStr += str[i]
}
console.log(newStr)

Collapse
ryands17 profile image
Ryan Dsouza

Great one! I though have a slightly different take if you don't want to create an intermediate array :)

function revFunction(str){
   const reversedString = [];
   for(let i = str.length - 1; i >= 0; i--){
       reversedString.push(str[i]);
   }
   return reversedString.join('');
};
Collapse
jpantunes profile image
JP Antunes

Using recursion so that only half the string is looped over:

const strReverso = ([...str], i = 0) => {
    return i < str.length / 2
            ? ([ str[i], str[str.length - 1 - i] ] = [ str[str.length - 1 - i], str[i] ], strReverso(str, ++i))
            : str.join('');
}
Collapse
hammertoe profile image
Matt Hamilton

In Python:

More verbose using a for loop:

def revFunction(str):
  arr = []
  for i in range(len(str)):
    arr.append(str[-i-1])
  return ''.join(arr)

More concise, using a list comprehension:

def revFunction(str):
  return ''.join([str[-i-1] for i in range(len(str))])
Collapse
catcarbn profile image
Cat Carbonell Author

Yesss I was waiting for a Python response!!!

Collapse
hammertoe profile image
Matt Hamilton

Actually just realised an even more concise way in Python. The slice operator takes a step as an optional 3rd argument, and I just found out the step can be negative.

>>> str = "Reverse me!"
>>> str[::-1]
'!em esreveR'

So...

def revFunction(str):
  return str[::-1]
Collapse
htshah profile image
Het Shah

How about this solution?

const reverse = ([...str]) => {
  const len = str.length;
  for(let i=0;i<len/2;i++){
    [str[i],str[len-i]] = [str[len-i],str[i]];
  }

  return str.join('');
}
Collapse
htshah profile image
Het Shah

Or not so optimized but shorter code:

const reverse2 = ([...str]) => 
    str.map((ch,i)=>str[str.length-1-i]).join('');
Collapse
yavuztas profile image
Yavuz Tas

Here is my solution a little bit different. Sacrifices memory in favor of speed, reversing a string in log(n) time complexity :)

function reverseByDivide(input){
  if(input.length < 2)
    return input
  var left = input.substring(0, input.length/2)
  var right = input.substring(input.length/2, input.length)
  return reverseByDivide(right) + reverseByDivide(left)
}
Collapse
graciegregory profile image
Gracie Gregory (she/her)

I love this series!

Collapse
miketalbot profile image
Mike Talbot

It's an interesting problem because it drives for a more optimal solution rather than desiring some super terse response I think. Though clearly .reverse() is highly optimised and terse! On DEV we often see solutions to problems written deliberately functionally (I do this a lot). Asking for no .reduce() definitely pushes us to realise we are being asked for an actual function not some kind of super expression and we should therefore be able to strive for optimal performance and memory use.

I run a lot of interviews, in this question I'd be looking for the following in the answer:

  • Don't use string appending - if the string was long this is a very slow solution - the result should concatenate an output array using .join()
  • Don't build an array using the spread operator at each step, it's even worse than string appending for performance and memory usage/garbage collection.
  • An optimal solution will cache commonly dereferenced properties to improve performance

Along with another commenter I also like your use of pop() very smart that. I think there's a slight error in it though - surely your function adds one too many characters? <=str.length - overall your solution is great.

Minimised space usage would have me making this hybrid of solutions mentioned:

function reverseString(str) {
     const source = str.split('')
     const swap = source.length >> 1
     for(let i = 0, j = source.length-1; i < swap;i++,j--) {
         let a = source[i]
         source[i] = source[j]
         source[j] = a
     }
     return source.join('')
}

  • Writing out that variable swap rather than using [source[i], source[j]] = [source[j], source[i]] avoids creating 2 arrays on every loop. These would be quickly garbage collected but it depends on the browser as to just how much memory/time that uses.
  • This has only one array being used and so reduces allocations
Collapse
catcarbn profile image
Cat Carbonell Author

I actually used splitString.length at first during the interview, but I wasn't getting the right result-- I came up short. Then I realized I needed to use str.length instead to get the desired result, and it was what the interviewer was looking for.

Thank you for your well-thought-out, detailed comment! I will keep those pointers in mind during the next technical interview.

Collapse
miketalbot profile image
Mike Talbot

Ah well I'd have made that mistake as well then :) Fair enough!

Collapse
johannesjo profile image
Johannes Millan

Performance is one way to look at it, another is readability and ease of use. If you assume only reasonably short strings and a reasonable amount of iterations then I would argue that the easier readable solution is the better one, as it is inviting less misunderstandings and saves time every time a developer reads your code. Just mentioning that so you don't judge your interviewees prematurely only on performance ;)

Collapse
mikeyglitz profile image
mikeyGlitz

For those who favor a more functional approach:

const str = 'Please reverse me';
const reverse = str.split('').reduce((acc, curr) => [curr, ...acc], []).join();
console.info(reverse);

Output:

em esreveR esaelP
Collapse
catcarbn profile image
Cat Carbonell Author

Thanks for sharing, but one of the stipulations was that you can’t use reduce! 😅

Collapse
mikeyglitz profile image
mikeyGlitz

My bad -- missed that part.

Thread Thread
catcarbn profile image
Cat Carbonell Author

That’s okay! Your solution is pretty slick. I was thinking of using reduce until he said not to haha.

Collapse
gerbosan profile image
Carlos A.

XD
Is so cool to read so many possibilities and some are quite elegant. Though it is kind of a simple example, as you have mentioned, the goal is to show your communication skills and your language knowledge.

const testText = "Please, reverse me!";
const reverseFunction = text => {
  const arrayText = Array.from(text)
  const reversedText = [];
  arrayText.forEach(elem => {
    reversedText.unshift(elem)
  });
  return reversedText.join('');
}

Here's what came to my mind. Though, I wonder about the JS version, could that be a valid question? Don't forget to review and clean your code. Finally, don't stay quiet while developing, speak your thought process, so your interviewer can follow you.

Again, thank you for the chance. =)

Collapse
elleattwell profile image
Harry Balls

Pretty cool. Check my solution.

private static object ReverseString(string input)
{
var str = "";
int index = input.Length - 1;
while (index >= 0)
{
str += $"{input[index--]}";
}
return str;
}

Collapse
developmentvargamarcel profile image
development-vargamarcel

A string is an array by default so you also could unshift all elements in an empty array and then join. Right?

Collapse
catcarbn profile image
Cat Carbonell Author

I thought a string was a string by default. If you unshift() a string, would that throw an error?

I’m not by a computer right now to try it out lol