LeetCode 2779 - Maximum Beauty of an Array After Applying Operation
This problem asks us to determine the maximum "beauty" of an array after performing a set of allowed operations. Specifically, the beauty is defined as the length of the longest subsequence consisting of equal elements.
Difficulty: 🟡 Medium
Topics: Array, Binary Search, Sliding Window, Sorting
Solution
Problem Understanding
This problem asks us to determine the maximum "beauty" of an array after performing a set of allowed operations. Specifically, the beauty is defined as the length of the longest subsequence consisting of equal elements. The operation lets us pick an element at index i (only once per index) and change it to any integer within the range [nums[i] - k, nums[i] + k]. The challenge is to select numbers to maximize the length of the subsequence of equal numbers after these operations.
The input consists of an array of integers nums and a non-negative integer k. The array length can be up to 10^5, and individual elements can also be as large as 10^5. These constraints indicate that a brute-force solution examining all possible combinations would be infeasible, and we must aim for an efficient solution that scales linearly or near-linearly with the array size.
Important edge cases include arrays where all elements are already equal, arrays with very large gaps between numbers relative to k, and cases where k = 0 (no changes are allowed).
Approaches
A brute-force approach would try every possible integer in the range [nums[i]-k, nums[i]+k] for each index and compute the resulting maximum subsequence length. This is correct in principle but exponentially slow, as it would require exploring an enormous number of combinations, making it impractical for arrays of size 10^5.
The key insight for an optimal solution is to realize that the problem reduces to finding the largest group of numbers whose "adjustment ranges" overlap. For each number num, we can define its interval as [num - k, num + k]. To maximize the number of equal elements, we need to find a point that lies in the most intervals. This is equivalent to a classic "sweep line" problem or interval counting. Sorting the array and using a sliding window allows us to efficiently count how many numbers can be adjusted to the same target.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O((2k+1)^n) | O(n) | Enumerate all possible values for each index, infeasible for large n |
| Optimal | O(n log n) | O(n) | Sort the array and use sliding window to find overlapping adjustment ranges |
Algorithm Walkthrough
- Sort the array
nums. Sorting helps us efficiently manage overlapping intervals because consecutive numbers in a sorted array are more likely to have overlapping ranges. - Initialize two pointers,
leftandright, both starting at 0. These define a sliding window of numbers that can potentially be adjusted to the same value. - Iterate
rightfrom 0 to the end of the array. For eachnums[right], determine ifnums[right]can be adjusted to overlap withnums[left]. The condition isnums[right] - nums[left] <= 2 * k. If it is satisfied, includenums[right]in the current window. - If
nums[right] - nums[left] > 2 * k, incrementleftuntil the condition is satisfied. This maintains the invariant that all numbers betweenleftandrightcan be adjusted to a single number. - Track the maximum size of the sliding window during this process. This size represents the maximum beauty achievable.
- Return the maximum beauty found.
Why it works: Each number can be adjusted by ±k, so two numbers can be made equal if their difference is at most 2k. The sliding window ensures that all numbers within it satisfy this property, and thus can all be adjusted to the same value, guaranteeing correctness.
Python Solution
from typing import List
class Solution:
def maximumBeauty(self, nums: List[int], k: int) -> int:
nums.sort()
max_beauty = 0
left = 0
for right in range(len(nums)):
while nums[right] - nums[left] > 2 * k:
left += 1
max_beauty = max(max_beauty, right - left + 1)
return max_beauty
The Python implementation first sorts the array and initializes the sliding window pointers. The inner while loop adjusts the left pointer to ensure all numbers in the current window can be adjusted to the same value. The window size is updated at each step to track the maximum beauty.
Go Solution
import "sort"
func maximumBeauty(nums []int, k int) int {
sort.Ints(nums)
maxBeauty := 0
left := 0
for right := 0; right < len(nums); right++ {
for nums[right]-nums[left] > 2*k {
left++
}
if right-left+1 > maxBeauty {
maxBeauty = right - left + 1
}
}
return maxBeauty
}
In Go, the approach is the same. Sorting is performed using sort.Ints. The sliding window uses indices left and right. Care is taken to handle slice boundaries correctly. Go does not require type hints like Python.
Worked Examples
Example 1: nums = [4,6,1,2], k = 2
Step-by-step:
| nums sorted | left | right | window valid? | window size | max_beauty |
|---|---|---|---|---|---|
| [1,2,4,6] | 0 | 0 | yes | 1 | 1 |
| [1,2,4,6] | 0 | 1 | yes (2-1 <=4) | 2 | 2 |
| [1,2,4,6] | 0 | 2 | yes (4-1 <=4) | 3 | 3 |
| [1,2,4,6] | 1 | 3 | no (6-2>4) | adjust left | 3 |
Maximum beauty is 3.
Example 2: nums = [1,1,1,1], k = 10
All elements are equal, difference never exceeds 2k = 20. Maximum beauty is 4.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n log n) | Sorting takes O(n log n), sliding window takes O(n) |
| Space | O(1) | No extra space besides pointers, in-place sorting possible |
The sorting dominates the complexity. The sliding window runs in linear time because each element is visited at most twice.
Test Cases
# Provided examples
assert Solution().maximumBeauty([4,6,1,2], 2) == 3 # Example 1
assert Solution().maximumBeauty([1,1,1,1], 10) == 4 # Example 2
# Edge and additional cases
assert Solution().maximumBeauty([1], 0) == 1 # Single element
assert Solution().maximumBeauty([1,5,9,13], 2) == 1 # Non-overlapping
assert Solution().maximumBeauty([1,2,3,4,5], 10) == 5 # Large k
assert Solution().maximumBeauty([1,2,3,2,1], 1) == 3 # Middle overlap
| Test | Why |
|---|---|
| [4,6,1,2], 2 | Checks basic adjustment and max beauty calculation |
| [1,1,1,1], 10 | All elements already equal |
| [1], 0 | Minimal input |
| [1,5,9,13], 2 | No elements can be adjusted to match |
| [1,2,3,4,5], 10 | Large k allows all elements to align |
| [1,2,3,2,1], 1 | Overlapping ranges in the middle |
Edge Cases
One edge case is when k = 0. No adjustments are allowed, so the maximum beauty is simply the frequency of the most common element. The sliding window correctly reduces to counting identical elements.
Another edge case is when all elements are equal. The algorithm correctly identifies that all elements can form the maximum subsequence without any adjustments.
A third edge case is when elements are very far apart relative to k. The sliding window efficiently skips numbers that cannot overlap without considering unnecessary combinations, ensuring correctness and efficiency.