Posted: 6 Dec, 2020
Difficulty: Moderate


Try Problem

Gary is bored and wants to play an interesting but tough game. So he figured out a new board game called "destroy the neighbours". In this game, there are N integers on a board. In one move, he can pick any integer x from the board, and then all the integers with value x + 1 or x - 1 get destroyed. This move will give him x points.

He plays the game until the board becomes empty. But as he wants to show this game to his friend Steven, he wants to learn techniques to maximize the points to show off. Can you help Gary in finding out the maximum points he receives from the game?

Input Format:
The first line of input contains an integer ‘T’, denoting the number of test cases. Then each test case follows.

The first line of each test case contains the Integer ‘N’ denoting the number of elements in the array.

The second and the last line of each test case contains ‘N’ single space-separated integers representing the elements of the array.
Output Format:
For each test case, print a single integer ‘X’, denoting the maximum points he receives from the game.

Output of each test case will be printed on a separate line.
You do not need to print anything, it has already been taken care of. Just implement the given function.
1 <= T <= 5
1 <= N <= 10 ^ 5
1 <= arr[i] <= 10 ^ 6

Time Limit: 1 sec.
Approach 1

The idea is to store the frequency of each number from 0 to maximum element M.

Now for each element from 0 to M, there are two choices: either we pick it or skip it.

So, we can break the problem into subproblems using the following observation:

  1. If we pick element ‘x’,  we must skip ‘x’ + 1.
  2. If we don’t pick ‘x’ then we may pick ‘x’ + 1 or skip it.

Let P(i, d) be the maximum point we can collect by picking elements from ‘i’ to M where 0 <= d <=1, if d is 0 it means we have picked the previous( i - 1 th) element else not.


P(i, 0) = max( P(i + 1, 1) + frequency[i] * i, P(i + 1, 0))

P(i, 1) = P(i + 1, 0)

This gives the optimal substructure.


Algorithm :


The steps are as follows:

  • Run a loop from 0 to ‘n’ and store the maximum element in the variable ‘M’.
  • Take a frequency array ‘frequency’ and store the initial frequency of all elements from 1 to ‘M’ to 0.
  • Run a loop from 0 to 'n'.
    • Update the frequency of each number Frequency[ arr[i] ]++.
  • Make a helper function ‘helper(frequency, idx, M, d).
  • Take a variable ‘ans’ and store the maximum of helper(frequency, 0, M, 0) and helper(frequency, 0, M, 1).
  • Return ‘ans’.

Description of helper(frequency, idx, 1001, d) function

  • If 'idx' is equal to 'n' return 0.
  • Take a variable 'ans'
  • If 'd' is equal to 0, it means previous element was not picked
    • Store the maximum of when we pick element at 'idx' and if we don't pick it and store in ‘ans’  i.e ‘ans’ = max(helper(frequency, idx + 1, n, 1) + frequency[idx] * idx, helper(frequency, idx + 1, n, 0)).
  • Else previous element was picked
    • Skip this element and recursively call the ‘helper’ function on the next index i.e ‘ans’ = helper(frequency, idx + 1, n, 0).
Try Problem