diff --git a/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/README.md b/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/README.md index 9c6617eee..40344b572 100755 --- a/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/README.md +++ b/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/README.md @@ -1,28 +1,39 @@ # [3186.Maximum Total Damage With Spell Casting][title] -> [!WARNING|style:flat] -> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm) - ## Description +A magician has various spells. + +You are given an array `power`, where each element represents the damage of a spell. Multiple spells can have the same damage value. + +It is a known fact that if a magician decides to cast a spell with a damage of `power[i]`, they **cannot** cast any spell with a damage of `power[i] - 2`, `power[i] - 1`, `power[i] + 1`, or `power[i] + 2`. + +Each spell can be cast **only once**. + +Return the **maximum** possible total damage that a magician can cast. **Example 1:** ``` -Input: a = "11", b = "1" -Output: "100" -``` +Input: power = [1,1,3,4] -## 题意 -> ... +Output: 6 -## 题解 +Explanation: -### 思路1 -> ... -Maximum Total Damage With Spell Casting -```go +The maximum possible damage of 6 is produced by casting spells 0, 1, 3 with damage 1, 1, 4. ``` +**Example 2:** + +``` +Input: power = [7,1,6,6] + +Output: 13 + +Explanation: + +The maximum possible damage of 13 is produced by casting spells 1, 2, 3 with damage 1, 6, 6. +``` ## 结语 diff --git a/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution.go b/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution.go index d115ccf5e..3c03ec295 100644 --- a/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution.go +++ b/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution.go @@ -1,5 +1,78 @@ package Solution -func Solution(x bool) bool { - return x +import "sort" + +func Solution(power []int) int64 { + if len(power) == 0 { + return 0 + } + + // 1. Calculate Total Damage per Value and collect unique damage values. + damageSums := make(map[int]int64) + for _, p := range power { + damageSums[p] += int64(p) + } + + // Get all unique damage values and sort them. + var uniqueDamages []int + for d := range damageSums { + uniqueDamages = append(uniqueDamages, d) + } + sort.Ints(uniqueDamages) + + M := len(uniqueDamages) + if M == 0 { + return 0 + } + + // 2. Dynamic Programming Array F. + // F[i] stores the max total damage considering spells with damage + // up to and including uniqueDamages[i]. + F := make([]int64, M) + + // F[0] Base Case: + F[0] = damageSums[uniqueDamages[0]] + + // 3. DP Iteration: + for i := 1; i < M; i++ { + currentDamage := uniqueDamages[i] + D_i := damageSums[currentDamage] + + // Option 1: Skip spells of currentDamage. + // Max damage is F[i-1]. + skipDamage := F[i-1] + + // Option 2: Cast all spells of currentDamage. + // Gain D_i. Must add to the max damage achieved up to damage currentDamage - 3. + + // Find the index 'j' of the *largest* unique damage value <= currentDamage - 3. + // We use sort.Search to find the first element > currentDamage - 3, then step back. + + target := currentDamage - 3 + + // Search for the first index 'k' where uniqueDamages[k] > target. + // Since sort.Search is not available for a custom search over a slice + // and we need to find the index for uniqueDamages, we use sort.SearchInts + // which is equivalent to finding the insertion point. + + // 'k' is the index of the first element STRICTLY GREATER THAN target. + k := sort.SearchInts(uniqueDamages, target+1) + + // The index of the largest element <= target is k-1. + j := k - 1 + + var prevMaxDamage int64 // Will be 0 if no such spell exists (j < 0). + if j >= 0 { + // prevMaxDamage is the max damage considering spells up to uniqueDamages[j]. + prevMaxDamage = F[j] + } + + castDamage := D_i + prevMaxDamage + + // F[i] = max(Option 1, Option 2) + F[i] = max(skipDamage, castDamage) + } + + // The result is the maximum damage considering all unique damage values. + return F[M-1] } diff --git a/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution_test.go b/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution_test.go index 14ff50eb4..862501a9d 100644 --- a/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution_test.go +++ b/leetcode/3101-3200/3186.Maximum-Total-Damage-With-Spell-Casting/Solution_test.go @@ -10,12 +10,11 @@ func TestSolution(t *testing.T) { // 测试用例 cases := []struct { name string - inputs bool - expect bool + inputs []int + expect int64 }{ - {"TestCase", true, true}, - {"TestCase", true, true}, - {"TestCase", false, false}, + {"TestCase1", []int{1, 1, 3, 4}, 6}, + {"TestCase2", []int{7, 1, 6, 6}, 13}, } // 开始测试 @@ -30,10 +29,10 @@ func TestSolution(t *testing.T) { } } -// 压力测试 +// 压力测试 func BenchmarkSolution(b *testing.B) { } -// 使用案列 +// 使用案列 func ExampleSolution() { }