2640. Find the Score of All Prefixes of an Array
Problem Description
The problem provides us with an array arr
. We are asked to calculate a "conversion" array based on this original array. The conversion array conver
is defined such that each of its elements conver[i]
is the sum of arr[i]
and the maximum value in the subarray arr[0..i]
, which includes all elements from the start of the array up to the current index i
.
In addition to this, we need to find the "score" of each prefix of the original array arr
. A prefix arr[0..i]
includes all elements in the array from index 0
to index i
. The score of a prefix is the sum of all the values in its conversion array. So for each prefix, we calculate its score and store it in an output array ans
, where ans[i]
equals the score of the prefix arr[0..i]
.
To summarize, the problem is asking us to:
- For each index
i
in the input arraynums
, calculate the conversion arrayconver
asconver[i] = nums[i] + max(nums[0..i])
. - Calculate the score for each prefix
nums[0..i]
as the sum ofconver[0..i]
. - Return an array
ans
where eachans[i]
is the score of the prefixnums[0..i]
.
Intuition
To approach this problem, we need to iterate through the input array nums
to build both the conversion array conver
and keep track of the sum for calculating the score simultaneously.
-
Iterating Through the Array: As we iterate through
nums
, we keep track of the maximum value found so far; this value representsmax(nums[0..i])
at each step. -
Computing the Conversion Values: For each index
i
, we simply addnums[i]
to this maximum value to get our currentconver[i]
. -
Accumulating the Scores: To calculate the score of the prefix, we also need to accumulate the scores obtained from previous prefixes. This can be done by maintaining a running sum of the conversion values as we proceed. The score up to the current prefix is the sum of the current
conver[i]
and the score of the previous prefix (which we have been accumulating). For the first element in the array, since there is no previous prefix, the score is simplynums[0] + max(nums[0])
, which is justnums[0] * 2
. -
Handling the First Element: We handle the first element as a special case, our code checks if
i
is0
and, if so, it doesn't add the score of the previous prefix (since there is none) but simply thenums[i] * 2
.
This process ensures that we only need to traverse the array once. We do not need to recalculate the maximum or the sum for each prefix from scratch.
The code implements these steps through the following logic:
- We initialize the maximum value
mx
as0
, and we start with an answer arrayans
of zeros. - We iterate through the input array
nums
, updatemx
to the maximum value so far, and calculateans[i]
. - Finally, return the populated
ans
array as the result.
Learn more about Prefix Sum patterns.
Solution Approach
The implementation uses a simple for
loop to iterate over the elements of the input array nums
, while maintaining two key pieces of information: the maximum value encountered so far (mx
) and the accumulated score for each prefix (ans[i]
). Here's a detailed walkthrough of the implementation:
-
Initialization: Before the loop starts, an array
ans
of zeros with the same length asnums
is created to store the scores for each prefix. The variablemx
is initialized to0
to keep track of the maximum value seen at each step during the iteration. -
Enumeration: The code uses
enumerate
to iterate overnums
, giving us both the indexi
and the valuex
at each step. Theenumerate
function is a common pattern when both the element and its index are needed. -
Updating the Maximum Value: As we traverse the array, the maximum value so far is updated by comparing the current value
x
with the last recorded maximummx
and assigning the greater of the two tomx
.mx = max(mx, x)
-
Calculation of Conversion Values and Accumulating Scores: For each index
i
, the current conversion value is computed asx + mx
. The score of the current prefix is the sum of this conversion value and the score of the previous prefix, which we have stored inans[i - 1]
. Sinceans
is initialized to have zeros, wheni
is0
,ans[i - 1]
does not exist and we handle this by adding0
instead.ans[i] = x + mx + (0 if i == 0 else ans[i - 1])
-
Data Structures: The solution uses two main data structures: a list
ans
to hold the scores of the prefixes and a simple variablemx
to keep track of the running maximum. No additional complex data structures are required to implement this solution effectively. -
Algorithm Complexity: The time complexity of this implementation is O(n) where n is the length of the
nums
because it makes a single pass through the input array. The space complexity is also O(n) due to the space used by theans
array. This efficient use of time and space makes the solution optimal for this problem.
In conclusion, the solution leverages a single linear scan, a common algorithmic pattern used to minimize the time complexity by avoiding nested loops or recursive calls that could potentially increase the complexity. It efficiently computes the required maximal values and accumulated sums in one iteration by using constant space (apart from the output array) and in linear time.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through an example to illustrate the solution approach using the following input array nums
:
nums = [1, 3, 5, 2]
-
Initialization: Before we begin, we create an array
ans
of zeros with the same length asnums
to store the scores for each prefix. Also, we initialize the variablemx
to0
.ans = [0, 0, 0, 0] // to hold the results mx = 0 // maximum value encountered so far
-
Processing the First Element: We start with the element at index
0
which is1
.mx = max(mx, nums[0]) // mx becomes 1, since max(0, 1) is 1 ans[0] = nums[0] + mx // ans[0] becomes 1 + 1 = 2
After processing the first element, our array
ans
andmx
variable are updated as:ans = [2, 0, 0, 0] mx = 1
-
Processing the Second Element: Moving on to the element at index
1
which is3
.mx = max(mx, nums[1]) // mx is updated to 3 ans[1] = nums[1] + mx + ans[0] // ans[1] is 3 + 3 + 2 = 8
Now
ans
andmx
are:ans = [2, 8, 0, 0] mx = 3
-
Processing the Third Element: For the element at index
2
which is5
.mx = max(mx, nums[2]) // mx stays at 5 ans[2] = nums[2] + mx + ans[1] // ans[2] is 5 + 5 + 8 = 18
The updated
ans
andmx
:ans = [2, 8, 18, 0] mx = 5
-
Processing the Last Element: Finally, for the element at index
3
which is2
.mx = max(mx, nums[3]) // mx stays at 5, since max(5, 2) is 5 ans[3] = nums[3] + mx + ans[2] // ans[3] is 2 + 5 + 18 = 25
We have our final
ans
array:ans = [2, 8, 18, 25]
As a result, for each prefix of the array nums
, we have calculated the corresponding scores and stored them in the ans
array. The scores indicate the sum of the values in the conversion array for each prefix. Thus, the final output for the input nums = [1, 3, 5, 2]
is [2, 8, 18, 25]
. This walkthrough demonstrates how our approach effectively processes each element of the input array to compute the scores in a step-by-step manner, updating the maximum value encountered and accumulating the scores for each prefix.
Solution Implementation
1class Solution:
2 def findPrefixScore(self, nums: List[int]) -> List[int]:
3 # Get the number of elements in the input list 'nums'.
4 num_elements = len(nums)
5
6 # Initialize a result list 'prefix_scores' with zeros of the same length as 'nums'.
7 prefix_scores = [0] * num_elements
8
9 # Initialize a variable 'max_prefix' that will hold the maximum prefix score so far.
10 max_prefix = 0
11
12 # Iterate over each number in 'nums' using its index and value.
13 for index, number in enumerate(nums):
14 # Update 'max_prefix' with the maximum between 'max_prefix' and the current number.
15 max_prefix = max(max_prefix, number)
16
17 # Compute the current prefix score.
18 # If it's the first element, then 'max_prefix' is the current number.
19 # Otherwise, it's the sum of the maximum prefix so far, the current number,
20 # and the previous prefix score.
21 if index == 0:
22 prefix_scores[index] = number + max_prefix
23 else:
24 prefix_scores[index] = number + max_prefix + prefix_scores[index - 1]
25
26 # Return the resulting list of prefix scores.
27 return prefix_scores
28
1class Solution {
2 // Method to find the prefix score for each number in the array
3 public long[] findPrefixScore(int[] nums) {
4 // n holds the length of the input array
5 int n = nums.length;
6
7 // Initialize the answer array with the same length as the input array
8 long[] answer = new long[n];
9
10 // Initialize a variable to keep track of the maximum value seen so far
11 int max = 0;
12
13 // Iterate over the input array to compute the prefix scores
14 for (int i = 0; i < n; ++i) {
15 // Update max if the current number is greater than the current max
16 max = Math.max(max, nums[i]);
17
18 // Calculate the prefix score for the current index i
19 // It is the sum of the current number, the maximum number seen so far,
20 // and the previous prefix score (if not the first element)
21 answer[i] = nums[i] + max + (i == 0 ? 0 : answer[i - 1]);
22 }
23
24 // Return the computed prefix scores
25 return answer;
26 }
27}
28
1#include <vector>
2#include <algorithm>
3
4class Solution {
5public:
6 // Function to find the prefix score of a given array of integers
7 vector<long long> findPrefixScore(vector<int>& nums) {
8 int size = nums.size(); // Get the size of the input vector.
9 vector<long long> prefixScore(size); // Initialize the result vector to store prefix scores.
10
11 int maxElement = 0; // Variable to keep track of the maximum element in the prefix.
12
13 // Iterate over the array to calculate prefix scores
14 for (int i = 0; i < size; ++i) {
15 maxElement = max(maxElement, nums[i]); // Update the maximum element in the prefix.
16
17 // The prefix score of the current position is the sum of the current element,
18 // the maximum element seen so far, and the previous prefix score (if not the first element).
19 prefixScore[i] = nums[i] + maxElement + (i == 0 ? 0 : prefixScore[i - 1]);
20 }
21
22 return prefixScore; // Return the final computed prefix scores.
23 }
24};
25
1function findPrefixScore(nums: number[]): number[] {
2 const numsLength = nums.length; // Length of the input array.
3 const prefixScores: number[] = new Array(numsLength); // Array to hold the prefix scores.
4
5 let maxNum: number = 0; // Variable to keep track of the maximum number encountered so far.
6
7 // Iterate through the array of numbers.
8 for (let index = 0; index < numsLength; ++index) {
9 // Update the maximum number if the current number is greater.
10 maxNum = Math.max(maxNum, nums[index]);
11
12 // Calculate the prefix score:
13 // It's the sum of the current number, the maximum number so far,
14 // and the prefix score of the previous element (if it exists).
15 prefixScores[index] = nums[index] + maxNum;
16 if (index > 0) {
17 prefixScores[index] += prefixScores[index - 1];
18 }
19 }
20
21 // Return the array of calculated prefix scores.
22 return prefixScores;
23}
24
Time and Space Complexity
Time Complexity
The provided code calculates the prefix score for a list of integers. The time complexity can be broken down as follows:
- There is a single loop that iterates over the list
nums
, which containsn
elements. - Inside the loop, the code performs constant time operations, including assignment, the
max
function on two integers, and arithmetic operations.
As a result, the loop will have n
iterations, and each iteration consists of constant time operations. This gives the time complexity as O(n)
.
Space Complexity
Analyzing the space complexity:
- The list
ans
is initialized with the same length asnums
, which addsO(n)
space. - The variables
n
,mx
, andi
use constant space (O(1)
). - No additional data structures or recursive calls that use space proportional to the size of the input.
Thus, the space complexity is O(n)
primarily due to the space required for the ans
list.
Learn more about how to find time and space complexity quickly using problem constraints.
Which algorithm is best for finding the shortest distance between two points in an unweighted graph?
Recommended Readings
Prefix Sum The prefix sum is an incredibly powerful and straightforward technique Its primary goal is to allow for constant time range sum queries on an array What is Prefix Sum The prefix sum of an array at index i is the sum of all numbers from index 0 to i By
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!