<p>A magician has various spells.</p>

<p>You are given an array <code>power</code>, where each element represents the damage of a spell. Multiple spells can have the same damage value.</p>

<p>It is a known fact that if a magician decides to cast a spell with a damage of <code>power[i]</code>, they <strong>cannot</strong> cast any spell with a damage of <code>power[i] - 2</code>, <code>power[i] - 1</code>, <code>power[i] + 1</code>, or <code>power[i] + 2</code>.</p>

<p>Each spell can be cast <strong>only once</strong>.</p>

<p>Return the <strong>maximum</strong> possible <em>total damage</em> that a magician can cast.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">power = [1,1,3,4]</span></p>

<p><strong>Output:</strong> <span class="example-io">6</span></p>

<p><strong>Explanation:</strong></p>

<p>The maximum possible damage of 6 is produced by casting spells 0, 1, 3 with damage 1, 1, 4.</p>
</div>

<p><strong class="example">Example 2:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">power = [7,1,6,6]</span></p>

<p><strong>Output:</strong> <span class="example-io">13</span></p>

<p><strong>Explanation:</strong></p>

<p>The maximum possible damage of 13 is produced by casting spells 1, 2, 3 with damage 1, 6, 6.</p>
</div>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= power.length &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= power[i] &lt;= 10<sup>9</sup></code></li>
</ul>

import numpy as np

class Solution:
    def maximumTotalDamage(self, power: List[int]) -> int:
        # compute unique damage array
        unique_sorted_damage = sorted(set(power))
        
        # compute frequency Map
        freq_dict = dict()
        for i in power:
            freq_dict[i] = freq_dict.get(i, 0) + 1

        # initialise max_damage_array 
        max_damage_array = [0]*len(unique_sorted_damage)
        max_damage_array[0] = unique_sorted_damage[0]*freq_dict[unique_sorted_damage[0]]
        for i in range(1,len(unique_sorted_damage)):
            current_total_damage = unique_sorted_damage[i]*freq_dict[unique_sorted_damage[i]]
            max_damage_array[i] = max_damage_array[i-1]

            # check if previous index is smaller than 2 of the current value
            previous_index = i - 1
            while previous_index >=0 and abs(unique_sorted_damage[previous_index]-unique_sorted_damage[i])<=2: 
                previous_index -= 1
            
            if previous_index >= 0:
                max_damage_array[i] = max(max_damage_array[i], max_damage_array[previous_index]+current_total_damage)
            else:
                max_damage_array[i]= max(max_damage_array[i], current_total_damage)
        return max_damage_array[-1]

        

51285