3452. Sum of Good Numbers
Problem Description
You are given an array of integers nums
and an integer k
. An element nums[i]
is considered good if it satisfies the following conditions:
- If the index
i - k
exists (meaningi >= k
), thennums[i]
must be strictly greater thannums[i - k]
- If the index
i + k
exists (meaningi + k < len(nums)
), thennums[i]
must be strictly greater thannums[i + k]
- If neither of these indices exists,
nums[i]
is automatically considered good
In other words, a number is good if it's strictly greater than the elements that are exactly k
positions away from it (both before and after), when such positions exist in the array.
Your task is to find and return the sum of all the good elements in the array.
For example, if nums = [3, 5, 1, 6, 2]
and k = 2
:
nums[0] = 3
: Only needs to be greater thannums[2] = 1
(sincei - k
doesn't exist). Since3 > 1
, it's good.nums[1] = 5
: Only needs to be greater thannums[3] = 6
(sincei - k
doesn't exist). Since5 ≤ 6
, it's not good.nums[2] = 1
: Needs to be greater than bothnums[0] = 3
andnums[4] = 2
. Since1 ≤ 3
, it's not good.nums[3] = 6
: Only needs to be greater thannums[1] = 5
(sincei + k
doesn't exist). Since6 > 5
, it's good.nums[4] = 2
: Only needs to be greater thannums[2] = 1
(sincei + k
doesn't exist). Since2 > 1
, it's good.
The sum of good elements would be 3 + 6 + 2 = 11
.
Intuition
The problem asks us to identify "good" numbers based on a simple comparison rule: each number must be strictly greater than its neighbors that are exactly k
positions away. This naturally leads to a direct checking approach.
The key insight is that we need to check each element against at most two other elements - one that's k
positions before it and one that's k
positions after it. However, we need to be careful about boundary conditions:
- For elements near the beginning of the array (where
i < k
), there's no elementk
positions before them - For elements near the end of the array (where
i + k >= len(nums)
), there's no elementk
positions after them
When these boundary positions don't exist, we simply don't need to check them - the element automatically passes that part of the condition.
The solution uses a clever optimization: instead of checking if an element is "good", we check if it's "not good". An element is not good if:
- There exists an element
k
positions before it AND the current element is not strictly greater than it (i.e.,nums[i] <= nums[i-k]
) - OR there exists an element
k
positions after it AND the current element is not strictly greater than it (i.e.,nums[i] <= nums[i+k]
)
If either of these conditions is true, we skip the element using continue
. Otherwise, we add it to our sum.
This reverse logic (checking for "not good" rather than "good") makes the code cleaner because we can use early exit conditions with continue
statements, avoiding nested if-statements and making the logic more straightforward to follow.
Solution Approach
The implementation uses a straightforward traversal approach to solve this problem. Let's walk through the solution step by step:
-
Initialize the answer variable: We start with
ans = 0
to accumulate the sum of all good numbers. -
Traverse the array: We use
enumerate()
to iterate through the array, getting both the indexi
and the valuex
at each position. -
Check conditions for each element: For each element
nums[i]
, we check if it fails to be a "good" number:- First condition check:
if i >= k and x <= nums[i - k]:
- We first verify that index
i - k
exists (by checkingi >= k
) - If it exists and
nums[i]
is not strictly greater thannums[i - k]
(meaningx <= nums[i - k]
), then this element is not good - We use
continue
to skip this element and move to the next one
- We first verify that index
- Second condition check:
if i + k < len(nums) and x <= nums[i + k]:
- We verify that index
i + k
exists (by checkingi + k < len(nums)
) - If it exists and
nums[i]
is not strictly greater thannums[i + k]
(meaningx <= nums[i + k]
), then this element is not good - We use
continue
to skip this element
- We verify that index
- First condition check:
-
Add good numbers to the sum: If an element passes both checks (doesn't hit either
continue
statement), it means:- Either the comparison indices don't exist (boundary cases)
- OR the element is strictly greater than the elements at those indices
In both cases, the element is "good", so we add it to our answer:
ans += x
-
Return the result: After traversing the entire array, we return the accumulated sum.
The time complexity is O(n)
where n
is the length of the array, as we visit each element exactly once. The space complexity is O(1)
as we only use a constant amount of extra space for the answer variable.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [7, 2, 9, 4, 8]
and k = 2
:
Initial setup: ans = 0
Iteration 1: i = 0, x = 7
- Check
i >= k
:0 >= 2
? No, skip first condition - Check
i + k < len(nums)
:0 + 2 < 5
? Yes, check if7 <= nums[2]
nums[2] = 9
, so7 <= 9
? Yes, this is true- Element is NOT good,
continue
to next iteration
ans
remains 0
Iteration 2: i = 1, x = 2
- Check
i >= k
:1 >= 2
? No, skip first condition - Check
i + k < len(nums)
:1 + 2 < 5
? Yes, check if2 <= nums[3]
nums[3] = 4
, so2 <= 4
? Yes, this is true- Element is NOT good,
continue
to next iteration
ans
remains 0
Iteration 3: i = 2, x = 9
- Check
i >= k
:2 >= 2
? Yes, check if9 <= nums[0]
nums[0] = 7
, so9 <= 7
? No, this is false, condition passes
- Check
i + k < len(nums)
:2 + 2 < 5
? Yes, check if9 <= nums[4]
nums[4] = 8
, so9 <= 8
? No, this is false, condition passes
- Both conditions pass, element is GOOD!
ans = 0 + 9 = 9
Iteration 4: i = 3, x = 4
- Check
i >= k
:3 >= 2
? Yes, check if4 <= nums[1]
nums[1] = 2
, so4 <= 2
? No, this is false, condition passes
- Check
i + k < len(nums)
:3 + 2 < 5
? No, skip second condition - Element is GOOD!
ans = 9 + 4 = 13
Iteration 5: i = 4, x = 8
- Check
i >= k
:4 >= 2
? Yes, check if8 <= nums[2]
nums[2] = 9
, so8 <= 9
? Yes, this is true- Element is NOT good,
continue
ans
remains 13
Final Result: The sum of good elements is 13 (elements 9 and 4 are good).
Solution Implementation
1class Solution:
2 def sumOfGoodNumbers(self, nums: List[int], k: int) -> int:
3 """
4 Calculate the sum of 'good' numbers in the array.
5 A number is 'good' if it's greater than all its k-distance neighbors that exist.
6
7 Args:
8 nums: List of integers
9 k: Distance parameter for checking neighbors
10
11 Returns:
12 Sum of all good numbers in the array
13 """
14 total_sum = 0
15
16 # Iterate through each element with its index
17 for index, current_value in enumerate(nums):
18 # Check left k-distance neighbor if it exists
19 # Skip this element if it's not greater than left neighbor
20 if index >= k and current_value <= nums[index - k]:
21 continue
22
23 # Check right k-distance neighbor if it exists
24 # Skip this element if it's not greater than right neighbor
25 if index + k < len(nums) and current_value <= nums[index + k]:
26 continue
27
28 # Current element is greater than all existing k-distance neighbors
29 # Add it to the sum
30 total_sum += current_value
31
32 return total_sum
33
1class Solution {
2 /**
3 * Calculates the sum of "good" numbers in the array.
4 * A number at index i is considered "good" if:
5 * - It is greater than the element k positions before it (if exists)
6 * - It is greater than the element k positions after it (if exists)
7 *
8 * @param nums the input array of integers
9 * @param k the distance to check for comparison
10 * @return the sum of all good numbers
11 */
12 public int sumOfGoodNumbers(int[] nums, int k) {
13 int sum = 0;
14 int arrayLength = nums.length;
15
16 // Iterate through each element in the array
17 for (int i = 0; i < arrayLength; i++) {
18 // Check if current element is not greater than element k positions before
19 if (i >= k && nums[i] <= nums[i - k]) {
20 continue; // Skip this element as it's not a good number
21 }
22
23 // Check if current element is not greater than element k positions after
24 if (i + k < arrayLength && nums[i] <= nums[i + k]) {
25 continue; // Skip this element as it's not a good number
26 }
27
28 // Current element is a good number, add it to the sum
29 sum += nums[i];
30 }
31
32 return sum;
33 }
34}
35
1class Solution {
2public:
3 int sumOfGoodNumbers(vector<int>& nums, int k) {
4 int sum = 0;
5 int n = nums.size();
6
7 // Iterate through each element in the array
8 for (int i = 0; i < n; ++i) {
9 // Check if current element is NOT a "good number"
10 // A number is NOT good if:
11
12 // 1. There exists an element k positions before that is >= current element
13 if (i >= k && nums[i] <= nums[i - k]) {
14 continue; // Skip this element as it's not a good number
15 }
16
17 // 2. There exists an element k positions after that is >= current element
18 if (i + k < n && nums[i] <= nums[i + k]) {
19 continue; // Skip this element as it's not a good number
20 }
21
22 // If we reach here, nums[i] is a "good number"
23 // (greater than elements at distance k in both directions, if they exist)
24 sum += nums[i];
25 }
26
27 return sum;
28 }
29};
30
1/**
2 * Calculates the sum of "good" numbers in an array.
3 * A number at index i is considered "good" if:
4 * - It is greater than the number k positions before it (if exists)
5 * - It is greater than the number k positions after it (if exists)
6 *
7 * @param nums - The input array of numbers
8 * @param k - The distance to check for neighboring elements
9 * @returns The sum of all good numbers
10 */
11function sumOfGoodNumbers(nums: number[], k: number): number {
12 const arrayLength: number = nums.length;
13 let totalSum: number = 0;
14
15 // Iterate through each element in the array
16 for (let currentIndex: number = 0; currentIndex < arrayLength; currentIndex++) {
17 // Check if current element is not greater than element k positions before
18 if (currentIndex >= k && nums[currentIndex] <= nums[currentIndex - k]) {
19 continue;
20 }
21
22 // Check if current element is not greater than element k positions after
23 if (currentIndex + k < arrayLength && nums[currentIndex] <= nums[currentIndex + k]) {
24 continue;
25 }
26
27 // If both conditions pass, add current element to sum
28 totalSum += nums[currentIndex];
29 }
30
31 return totalSum;
32}
33
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the array nums
. The algorithm iterates through the array exactly once using a single for loop with enumerate(nums)
. For each element at index i
, it performs at most two constant-time comparisons: checking if i >= k
and comparing x
with nums[i - k]
, and checking if i + k < len(nums)
and comparing x
with nums[i + k]
. Since these operations take O(1)
time and are performed for each of the n
elements, the overall time complexity is O(n)
.
The space complexity is O(1)
. The algorithm only uses a fixed amount of extra space for variables ans
, i
, and x
, regardless of the input size. No additional data structures that grow with the input size are created, making the space complexity constant.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Confusing Index Distance with Adjacent Elements
A frequent mistake is thinking that k
refers to adjacent elements rather than elements exactly k
positions away. For instance, with k=2
, you need to check positions i-2
and i+2
, NOT positions i-1
and i+1
.
Incorrect implementation:
# Wrong: Checking all elements within k distance
for j in range(max(0, i-k), min(len(nums), i+k+1)):
if j != i and nums[i] <= nums[j]:
# This checks too many elements!
Correct approach:
# Right: Only check elements at exactly k distance
if i >= k and nums[i] <= nums[i-k]:
continue
if i + k < len(nums) and nums[i] <= nums[i+k]:
continue
2. Using Non-Strict Comparison
The problem requires strictly greater comparison (>
), not greater-than-or-equal (>=
). Using the wrong comparison operator will include elements that should be excluded.
Incorrect:
if i >= k and current_value < nums[i - k]: # Wrong: should be <= continue
Correct:
if i >= k and current_value <= nums[i - k]: # Correct: element must be strictly greater continue
3. Incorrect Boundary Checking Logic
A subtle error is misunderstanding when an element is automatically "good". Elements are good by default when comparison indices don't exist, not when they fail the comparison.
Incorrect logic:
# Wrong: Treating out-of-bounds as automatic failure
is_good = True
if i >= k:
is_good = nums[i] > nums[i-k]
if i + k < len(nums):
is_good = is_good and nums[i] > nums[i+k]
# This fails when only one boundary exists
Correct logic:
# Right: Only fail when index exists AND comparison fails
is_good = True
if i >= k and nums[i] <= nums[i-k]:
is_good = False
if i + k < len(nums) and nums[i] <= nums[i+k]:
is_good = False
4. Off-by-One Errors in Index Validation
Be careful with the boundary conditions. The left boundary check should be i >= k
(not i > k
), and the right boundary should be i + k < len(nums)
(not i + k <= len(nums)
).
Example to verify boundaries:
- For an array of length 5 with
k=2
:- At index 0: Check index 2 (exists) but not index -2
- At index 2: Check indices 0 and 4 (both exist)
- At index 4: Check index 2 (exists) but not index 6
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Coding Interview 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
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 assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!