↓Skip to main content
  1. LeetCode/

LeetCode 1793: Maximum Score of a Good Subarray

·3 mins· ·
LeetCode Hard Two-Pointers Greedy Binary-Search Array Monotonic-Stack
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2026-01-29

  • Submissions: Wrong Answer ×3 → Accepted

Approach
#

A good subarray always contains k, so start from [k, k] and grow by one element to the left or right each step, from length 1 up to n.

Grow toward the larger neighbor: the score is minimum × length, and for a given length a larger minimum is better. Moving toward the larger neighbor lowers the minimum the least. After each step, update the answer with the current minimum × length.

At a boundary, only the other side can grow, until both ends are reached.

The same problem can be viewed with a monotonic stack: for each nums[i] as the minimum, find how far it extends left and right and count it only if the range contains k, the same family as the largest rectangle in a histogram (LeetCode 84).

My Attempts
#

My version computed the score after growing left and after growing right, and moved toward the higher one. All three WAs were boundary and update issues:

VersionProblem
Attempt 1The left-growth length was one short, the current minimum was never updated, and it moved right even with the right end at the boundary. For nums = [1, 1], k = 1, the answer is 2; it returned 1
Attempt 2When growing right, it updated the answer with the left-growth score. For nums = [1, 1], k = 0, the answer is 2; it returned 1
Attempt 3Looped while start >= 0 and end <= n - 1 and set the blocked side’s score to the current answer; on a tie it moved toward the blocked side, start became -1, and the loop ended before the other side finished growing. For nums = [2, 1, 1], k = 0, the whole array 1 × 3 = 3 is the answer; it returned 2

Looping while start > 0 or end < n - 1 and forcing the other side at a boundary passed.

Solution
#

class Solution:
    def maximumScore(self, nums: List[int], k: int) -> int:
        n = len(nums)
        i = j = k
        cur_min = best = nums[k]
        while i > 0 or j < n - 1:
            if i == 0 or (j < n - 1 and nums[j + 1] > nums[i - 1]):
                j += 1                             # grow right (left blocked, or right neighbor larger)
                cur_min = min(cur_min, nums[j])
            else:
                i -= 1                             # grow left
                cur_min = min(cur_min, nums[i])
            best = max(best, cur_min * (j - i + 1))
        return best

Comparing the two neighbor values directly is simpler than my original comparison of post-growth scores, with the same effect.

Complexity
#

Time O(n), space O(1).

Mistakes to Avoid
#

  • Forgetting to update the minimum after growing.
  • Growing toward a boundary, or ending the loop before the other side has finished.
  • The length is j - i + 1.

Interview Explanation
#

A good subarray always contains k, so I grow outward from k, each time toward the larger neighbor, because for the same length a larger minimum scores higher and the larger side lowers the minimum the least. After each step I update the answer with minimum × length, and once one side is at the boundary I only grow the other. Time O(n). A monotonic stack that finds each element’s range as the minimum, counting only ranges containing k, also works.

Related

LeetCode 611: Valid Triangle Number
·2 mins
LeetCode Medium Array Two-Pointers Binary-Search Greedy
LeetCode 611 note: sort, fix the longest side k, and use two pointers for the shorter sides; when the sum is large enough every i in between works, adding j - i at once
LeetCode 3555: Smallest Subarray to Sort in Every Sliding Window
·2 mins
LeetCode Medium Two-Pointers Greedy Sorting Array Monotonic-Stack
LeetCode 3555 note: every length-k window is one instance of LeetCode 581; with n only 1000, two O(k) scans per window are enough
LeetCode 581: Shortest Unsorted Continuous Subarray
·2 mins
LeetCode Medium Two-Pointers Greedy Sorting Array Monotonic-Stack
LeetCode 581 note: scanning left to right with a running max, the last index below it is the right boundary; scanning right to left with a running min, the last index above it is the left boundary
LeetCode 2972: Count the Number of Incremovable Subarrays II
·2 mins
LeetCode Hard Two-Pointers Binary-Search Array
LeetCode 2972 note: what remains is a strictly increasing prefix plus suffix; for each valid prefix end, a right-only pointer finds the first suffix start that can follow it, and every later start works too
LeetCode 1574: Shortest Subarray to be Removed to Make Array Sorted
·2 mins
LeetCode Medium Two-Pointers Binary-Search Array Monotonic-Stack
LeetCode 1574 note: what remains is a non-decreasing prefix plus a non-decreasing suffix; find the longest of each, then join them with two pointers
LeetCode 1989: Maximum Number of People That Can Be Caught in Tag
·3 mins
LeetCode Medium Two-Pointers Greedy Array
LeetCode 1989 note: process the “it” players left to right, each catching the leftmost uncaught person in range, with a right-only pointer to the next candidate