Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions codereview/maximumNonAdjacentElementSumIdentifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## Purpose

I recently came across an interview question that stumped me for a while
> Given a list of integers, write a function that returns the largest sum of non-adjacent numbers.

I am looking for feedback around both my implementation and the correctness of my proposed solution (I have some test
cases, but I could have missed a case).

## Approach

For arrays with `1` or `2` values, the answer is trivial.

For arrays with more than `2` values, keep track of the maximum sum from the preceding non-adjacent elements that
*includes the most recent non-adjacent element*, and the maximum sum from the preceding non-adjacent elements that
*excludes the most recent non-adjacent element*.

So for `[3, 1, 1, 5, 1]` at index `3`, the maximum sum from preceding non-adjacent elements that includes the most recent
non-adjacent element is `1`, while the maximum sum from preceding non-adjacent elements that excludes the most recent
non-adjacent element is `3`.

Taking the max of these two sums and adding them to the current value will produce the maximum sum for non-adjacent
elements up to that index. Continuing this process for each remaining index and then comparing the last two calculated
sums will produce the maximum sum.

Let's walk through this process with `[3, 1, 1, 5, 1]`.

* At index `0`, the max sum is `3`
* At index `1`, the max sum is `1`
* At index `2`, the max sum from including the most recent non-adjacent element is `3`, while the max sum from excluding
the most recent non-adjacent element is `0`. Thus, we choose `3` and add that to the current value (`1`). `4` is now
the max non-adjacent sum for index `2`.
* At index `3`, the max sum from including the most recent non-adjacent element is `1`, while the max sum from excluding
the most recent non-adjacent element is `3`. Thus, we choose `3` and add that to the current value (`5`). `8` is now
the max non-adjacent sum for index `3`.
* At index `4`, the max sum from including the most recent non-adjacent element is `4`, while the max sum from excluding
the most recent non-adjacent element is `3`. Thus, we choose `4` and add that to the current value (`1`). `6` is now
the max non-adjacent sum for index `4`.
* The final two sums were `8` and `6` - we take the max (`8`).

Apologies if this was confusing to follow, it was difficult to describe my thought process.

## Implementation

<!-- language: lang-java -->

public class MaximumNonAdjacentElementSumIdentifier {
public static int identify(int[] values) {
if (values == null || values.length == 0) {
throw new RuntimeException("Unable to identify sum");
}

if (values.length == 1) {
return values[0];
}

int firstSum = 0;
int secondSum = values[0];
int previousValueSum = values[1];

for (int i = 2; i < values.length; i++) {
int value = values[i];
int maximumCurrentElementSum = Math.max(firstSum, secondSum) + value;
firstSum = Math.max(firstSum, secondSum);
secondSum = previousValueSum;
previousValueSum = maximumCurrentElementSum;
}

return Math.max(secondSum, previousValueSum);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package problems.impl;

/**
* Given a list of integers, write a function that returns the largest sum of non-adjacent numbers.
*/

public class MaximumNonAdjacentElementSumIdentifier {
public static int identify(int[] values) {
if (values == null || values.length == 0) {
throw new RuntimeException("Unable to identify sum");
}

if (values.length == 1) {
return values[0];
}

int firstSum = 0;
int secondSum = values[0];
int previousValueSum = values[1];

for (int i = 2; i < values.length; i++) {
int value = values[i];
int maximumCurrentElementSum = Math.max(firstSum, secondSum) + value;
firstSum = Math.max(firstSum, secondSum);
secondSum = previousValueSum;
previousValueSum = maximumCurrentElementSum;
}

return Math.max(secondSum, previousValueSum);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package problems.impl;

import org.junit.Test;

import static org.junit.Assert.*;

public class MaximumNonAdjacentElementSumIdentifierTest {
@Test
public void itShouldIdentifySum1() {
int[] values = new int[] { 5, 1, 1, 7, 3};
int expected = 12;
assertEquals(expected, MaximumNonAdjacentElementSumIdentifier.identify(values));
}

@Test
public void itShouldThrowAnExceptionForNullValues() {
try {
MaximumNonAdjacentElementSumIdentifier.identify(null);
} catch (RuntimeException e) {
// expected
}
}

@Test
public void itShouldThrowAnExceptionForEmptyValues() {
try {
MaximumNonAdjacentElementSumIdentifier.identify(new int[] {});
} catch (RuntimeException e) {
// expected
}
}

@Test
public void itShouldReturnValueForSingleElementValues() {
int value = 5;
int[] values = new int[] { value };
assertEquals(value, MaximumNonAdjacentElementSumIdentifier.identify(values));
}

@Test
public void itShouldReturnGreaterValueForTwoElementValues() {
assertEquals(5, MaximumNonAdjacentElementSumIdentifier.identify(new int[]{4, 5}));
}

@Test
public void itShouldReturnGreatestSingleValueForThreeElementValues() {
assertEquals(3, MaximumNonAdjacentElementSumIdentifier.identify(new int[]{-1, 1, 3}));
}

@Test
public void itShouldReturnGreatestCombinedValuesForThreeElementValues() {
assertEquals(8, MaximumNonAdjacentElementSumIdentifier.identify(new int[]{2, 7, 6}));
}
}