Hey.
I have finally gotten out of a self-created rut to begin writing again, and whilst this bit of information may not be pertinent to this article, it is somewhat imperative to start this series (yes, series! yay us!) with "the why" this particular piece exists in the first place.
Background
Over the past couple of weeks, I have been tinkering about what to write. I largely settled on pieces about new stuff I have been learning in Java and Golang. Ultimately, I began considering writing about solving technical interview code challenges since I had been interviewing recently so here we go. Throughout this series, I will alternate between HackerRank and LeetCode problems with varying degrees of difficulty.
Now that we have the backstory out of the way, this first article in this series is a code challenge from HackerRrank.
Problem
The image above describes what the problem is, we are presented with an array of numbers and are expected to sum up four of the five numbers in the array, sorting the addition operation by index.
When the addition operation is complete, we are then required to log the smallest (min) and largest (max) numbers (MinMax) as the solution to the problem. The second part of the problem – which shows a sample input and its expected output – is represented in the image below.
Solution
We are presented with a function minMaxSum
that receives an array of positive integers arr
described in the example above. I approach solving this problem by first declaring a variable savedArr
and assigning an empty array to it to avoid mutating the original array arr
.
function miniMaxSum(arr) {
let savedArr = [];
for (let i = 0; i < arr.length; i++) {
if (i === 0) {
const minOne = arr.slice(1)
const reduceMinOne = minOne.reduce(reduceArr)
savedArr = [...savedArr, reduceMinOne]
}
// rest of code...
}
}
I instantiate a for
loop that runs the addition operation for as long as I need.
In the example, the first addition operation is carried out without the first element of the given array arr
(I have attached a photo below to help you remember).
I remove the first element of the array (arr.slice(1)
) and assign it to a variable minOne
, then I sum up the values of the new array minOne
using the array.reduce()
method and assign it to a new variable reduceMinOne
.
const reduceMinOne = minOne.reduce(reduceArr)
Taking a closer look at reduceMinOne
, there is a strange-looking dude on that line called reduceArr
that's yet to be introduced, so let's meet the good ol' chap.
function reduceArr(acc, value) {
return acc + value;
}
reduceArr
is a simple function that accepts two parameters (acc, value
) and returns the sum of both parameters.
Now that we understand what reduceArr
does, it becomes easier to understand how it is applied to the minOne
array like so: const reduceMinOne = minOne.reduce(reduceArr)
. I'd explain the array.reduce()
method but it is beyond the scope of this article, but you can read more about that bit here.
Remember savedArr
? I assigned an empty array to this variable, now let's update savedArr
, shall we?
savedArr = [...savedArr, reduceMinOne]
What the line above does is to "open up" the savedArr
variable using the spread operator (you can read more about the javascript spread operator here) and inserting the reduceMinOne
value into it.
Intermission...
Phew! We have been writing code for a while now so let's take a break and stare at a random gif on the internet.
Solution [Cont'd]
Okay, now that the first iteration of the loop has been handled, we need to deal with the rest, to do so, I introduced two new variables minTwo
and arrRest
.
function miniMaxSum(arr) {
let savedArr = [];
for (let i = 0; i < arr.length; i++) {
if (i === 0) {
const minOne = arr.slice(1)
const reduceMinOne = minOne.reduce(reduceArr)
savedArr = [...savedArr, reduceMinOne]
}
// new block of code
else {
const minTwo = arr.slice(i + 1)
const arrRest = arr.slice(0, i)
const combinedArr = arrRest.concat(minTwo)
const reduceMinRest = combinedArr.reduce(reduceArr)
savedArr = [...savedArr, reduceMinRest]
}
// rest of code...
}
}
To better understand variables minTwo
and arrRest
, let's have a second look at the example.
Points 2-5 expect us to run through the addition operation of the array, removing elements by index as we progress down the length of the array. So when I introduced const minTwo = arr.slice(i+1)
, I removed the first i element(s) (plus 1) where i = number of iterations. I have highlighted an explanation below so it's clearer.
// Example
var arr = [1, 2, 3, 4, 5]
// if i == 0
arr.slice(i) => // [2, 3, 4, 5]
arr.slice(i + 1) => // [3, 4, 5]
const arrRest = arr.slice(0, i)
begins the slice operation from index 0
and ends at index i
, returns a new array without including the element at index i
.
// Example
var arr = [1, 2, 3, 4, 5]
// if i == 0
arr.slice(i + 1) => // [3, 4, 5]
arr.slice(i, 0) => // [1]
There are two more variables I introduced, combinedArr
and reduceMinRest
.
const combinedArr = arrRest.concat(minTwo)
The simple line of code above combines (yeah, I know!) both variables arrRest
and minTwo
into one array, positioning the value of arrRest
in front of the new array combinedArr
.
reduceMinRest
uses the reducer function from earlier to find the sum of the elements in the combinedArr
like so: const reduceMinRest = combinedArr.reduce(reduceArr)
.
Then, I update the savedArr
array with the value from reduceMinRest
like so: savedArr = [...savedArr, reduceMinRest]
Alright, we're almost there. To arrive at the solution required, we must sort through savedArr
. Sorting helps us position the values in the array in ascending order.
function miniMaxSum(arr) {
let savedArr = [];
for (let i = 0; i < arr.length; i++) {
if (i === 0) {
const minOne = arr.slice(1)
const reduceMinOne = minOne.reduce(reduceArr)
savedArr = [...savedArr, reduceMinOne]
}
else {
const minTwo = arr.slice(i+1)
const arrRest = arr.slice(0, i)
const combinedArr = arrRest.concat(minTwo)
const reduceMinRest = combinedArr.reduce(reduceArr)
savedArr = [...savedArr, reduceMinRest]
}
// new block of code
if (savedArr.length === arr.length) {
const sortArr = savedArr.sort()
const min = sortArr.shift()
const max = sortArr.pop()
// solution
console.log(min, max)
}
}
Before I begin the sort operation, I first check to ensure there is no overflow and I have the exact number of expected values in savedArr
like so: if (savedArr.length === arr.length)
. I have also introduced three new variables: sortArr
, min
, and max
.
sortArr
sorts the array in ascending order using the sort()
method while min
returns the value in front of the array which by definition is the minimum sum obtained from the addition operation performed on the original array arr
and max
returns the value at the end of the array which is the maximum sum obtained from the addition operation performed on the original array arr
.
Running the code against the sample test case shows that the code produces the expected output with the sample input from the example.
Result
Submitting the code against the hidden test cases also shows that it passes and all is right in the world.
Postscript
I may have omitted to take into account certain constraints as I solved this, if you have a much better way of solving this problem, feel free to shoot me your answer(s). I'd love to take a look.
Cheers!