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
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@
* Unique Number Of Occurrences
* [Test Unique Occurrences](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/hashmap/unique_number_of_occurrences/test_unique_occurrences.py)
* Heap
* Maximal Score After K Operations
* [Test Maximal Score](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/heap/maximal_score_after_k_operations/test_maximal_score.py)
* Maximum Subsequence Score
* [Test Max Subsequence Score](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/heap/maximum_subsequence_score/test_max_subsequence_score.py)
* Min Cost Hire K Workers
Expand Down
76 changes: 76 additions & 0 deletions puzzles/heap/maximal_score_after_k_operations/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Maximal Score After Applying K Operations

You are given an array of integers nums and an integer k. You want to perform the following operation exactly k times:

You are given a 0-indexed array of integer nums and an integer k. Your task is to maximize a score through a series of
operations. Initially, your score is set to 0

In each operation:

1. Select an index i (where 0 ≤ i <nums.length).
2. Add the value of nums[i] to your score.
3. Replace nums[i] with ceil(nums[i] / 3).

Repeat this process exactly k times and return the highest score you can achieve.

> The ceiling function `ceil(value)` is the least integer greater than or equal to `value`.

Constraints:

- 1 ≤ nums.length, k ≤ 10^3
- 1 ≤ nums[i] ≤ 10^5

## Examples

Example 1:

![Example 1](images/examples/maximal_score_after_k_operations_example_1.png)
![Example 2](images/examples/maximal_score_after_k_operations_example_2.png)
![Example 3](images/examples/maximal_score_after_k_operations_example_3.png)

---

## Solution

This algorithm maximizes the score by iteratively selecting and reducing the largest elements from the array. It uses a
max heap to ensure efficient access to the largest element. Over k iterations, the algorithm repeatedly extracts the
largest value, adds it to the total score, reduces it by dividing it by 3 and rounding it up, and reinserts the reduced
value into the heap.

The steps of the algorithm are as follows:

1. Create a max heap to store all elements of nums.
2. Initialize a variable score to 0 to keep track of the accumulated score.
3. Iterate for k steps, and in each iteration, perform the following steps:
- Pop the largest value from the heap using heapq.heappop and store this value in a variable largest.
- Add this value to the score.
- Calculate the reduced value of the extracted element as math.ceil(largest / 3).
- Push the reduced value back into the heap using heapq.heappush to maintain the max heap.
4. After k iterations, return the accumulated score.

Let’s look at the following illustration to get a better understanding of the solution:

![Solution 1](images/solution/maximal_score_after_k_operations_solution_1.png)
![Solution 2](images/solution/maximal_score_after_k_operations_solution_2.png)
![Solution 3](images/solution/maximal_score_after_k_operations_solution_3.png)
![Solution 4](images/solution/maximal_score_after_k_operations_solution_4.png)
![Solution 5](images/solution/maximal_score_after_k_operations_solution_5.png)
![Solution 6](images/solution/maximal_score_after_k_operations_solution_6.png)
![Solution 7](images/solution/maximal_score_after_k_operations_solution_7.png)
![Solution 8](images/solution/maximal_score_after_k_operations_solution_8.png)
![Solution 9](images/solution/maximal_score_after_k_operations_solution_9.png)
![Solution 10](images/solution/maximal_score_after_k_operations_solution_10.png)
![Solution 11](images/solution/maximal_score_after_k_operations_solution_11.png)
![Solution 12](images/solution/maximal_score_after_k_operations_solution_12.png)
![Solution 13](images/solution/maximal_score_after_k_operations_solution_13.png)
![Solution 14](images/solution/maximal_score_after_k_operations_solution_14.png)
![Solution 15](images/solution/maximal_score_after_k_operations_solution_15.png)

### Time Complexity

In each iteration of the loop, pop from the heap takes O(log(n)), while pushing the updated value into the heap also
takes O(logn). As the loop runs k times, the total time complexity for the loop is O(klogn).

### Space Complexity

The space complexity is O(n) because the heap stores n elements, where n is the number of elements in nums.
26 changes: 26 additions & 0 deletions puzzles/heap/maximal_score_after_k_operations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import List
from math import ceil
import heapq


def max_score(nums: List[int], k: int) -> int:
score = 0

# if there are no elements, just return the score of 0
if len(nums) == 0:
return score

# a heapq provides a in-heap, so we'll have to use negative values to simulate a max-heap
# Create a max-heap by negating all values (heapq is a min-heap)
# This allows us to efficiently get the maximum element each time
max_heap = [-num for num in nums]
heapq.heapify(max_heap)

for _ in range(k):
# Extract the maximum element (most negative in our negated heap)
current_largest = -heapq.heappop(max_heap)
score += current_largest
reduced_value = ceil(current_largest / 3)
heapq.heappush(max_heap, -reduced_value)

return score
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import unittest
from . import max_score


class MaximalScoreAfterKOperationsTestCase(unittest.TestCase):
def test_1(self):
nums = [10,20,30,40,50]
k = 4
expected = 140
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_2(self):
nums = [5,12,7,3,10]
k = 3
expected = 29
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_3(self):
nums = [6,9,15]
k = 2
expected = 24
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_4(self):
nums = [1,10,3,3,3]
k = 3
expected = 17
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_5(self):
nums = [7,10,16]
k = 2
expected = 26
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_6(self):
nums = [5,120,7,30,10]
k = 3
expected = 190
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_7(self):
nums = [100,200,300,400,500]
k = 4
expected = 1400
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_8(self):
nums = [20,20,20,20]
k = 3
expected = 60
actual = max_score(nums, k)
self.assertEqual(expected, actual)

def test_9(self):
nums = [81698,68947,77662,46592,13226,37325,2800,22504,99833,77083,38068,40934,3640,33631,84634,66457,21309,
64949,94392,3553,68692,31662,17348,42805,32143,7099,88341,65391,8164,65035,22205,88755,80232,84970,
19213,36774,33975,47386,74761,4893,9040,8263,60379,88511,49040,89068,72601,17683,17871,46156,2805,10247,
54658,27427,51671,81935,59171,70215,56400,83874,9230,31194,98266,84404,1200,89589,70329,39209,19461,
19022,86927,26496,27561,96403,78150,47498,5696,78065,75672,44842,64855,19760,57351,7788,41209,89214,
24315,6398,60738,88636,71885,44987,28782,13700,78965,47534,82496,66162,89596,3646,73107,13112,28574,
37445,14997,98860]
k = 1000
expected = 7709375
actual = max_score(nums, k)
self.assertEqual(expected, actual)


if __name__ == '__main__':
unittest.main()
Loading