1. Problem Summary
You are given an integer array nums, and your task is to determine whether it is possible to make the array non-decreasing by modifying at most one element.
A non-decreasing array satisfies:
nums[i] <= nums[i+1] for all i
Rules:
- You may change at most one number
- You may change it to any value
- If already non-decreasing, return true
Example interpretation:
Input:
[4,2,3]
Modify 4 → 2 to get [2,2,3] → return true.
Input:
[4,2,1]
Needs at least two modifications → return false.
2. Key Insights
1. We only need to detect violations
A violation occurs when:
nums[i] > nums[i+1]
2. More than one violation → impossible
If we see two or more such drops, cannot fix with one modification.
3. When violation occurs, we must choose which number to modify
Two cases:
Case A: modify nums[i]
If:
i == 0 OR nums[i-1] <= nums[i+1]
then lowering nums[i] works.
Case B: modify nums[i+1]
Else:
nums[i+1] = nums[i]
4. We do not need to simulate all possibilities
One pass with adjustment logic is enough.
5. Correct handling avoids accidental new violations
Choosing the right side to adjust prevents cascading failures.
3. Approach
Single pass with violation counter
Steps:
- Initialize
violations = 0 - Loop through array indices from 0 to n-2
- If nums[i] > nums[i+1]:
- increment violations
- if violations > 1 → return false
- decide modification direction:
- if i == 0 OR nums[i-1] <= nums[i+1]:
modify nums[i] downward (conceptually)
else:
modify nums[i+1] upward (conceptually)
- if i == 0 OR nums[i-1] <= nums[i+1]:
- If loop completes, return true
We don’t need to truly modify array—just ensure feasibility.
4. Time and Space Complexity
Time Complexity:
O(N)
single scan through array
Space Complexity:
O(1)
no extra storage needed
5. Java Solution
class Solution {
public boolean checkPossibility(int[] nums) {
int violations = 0;
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] > nums[i + 1]) {
violations++;
if (violations > 1) {
return false;
}
if (i == 0 || nums[i - 1] <= nums[i + 1]) {
nums[i] = nums[i + 1];
} else {
nums[i + 1] = nums[i];
}
}
}
return true;
}
}
6. Dry Run Examples
Example 1
Input:
[4,2,3]
Check:
4 > 2 (violation = 1)
i == 0 → modify nums[0] → becomes 2
Resulting pattern valid
Output:
true
Example 2
Input:
[4,2,1]
Check:
4 > 2 (violation = 1)
modify nums[0] → becomes 2
Now array conceptually: [2,2,1]
Next:
2 > 1 (violation = 2) → fail
Output:
false
Example 3
Input:
[3,4,2,3]
Check:
4 > 2 (violation = 1)
nums[1] > nums[2] and nums[0] > nums[2]
so modify nums[2] → becomes 4
array becomes [3,4,4,3]
Next:
4 > 3 (violation = 2) → fail
Output:
false
Example 4
Input:
[1,2,3]
No violations
Output:
true
Example 5
Input:
[2,3,3,2,4]
Check:
3 > 2 (violation = 1)
nums[2] <= nums[4] → safe modify
Only one violation overall
Output:
true
7. Why This Solution Works
- Detecting violations is sufficient because only one modification allowed
- Smart choice of which element to conceptually adjust prevents chain-breaking
- Early exit avoids unnecessary processing
- Works for:
- negative numbers
- equal values
- long sequences
- edge boundaries
8. Common Mistakes
- Trying to brute force every possible modification
- Assuming always modify nums[i] (not always correct)
- Forgetting edge case at index 0
- Continuing after second violation
- Believing sorted means strictly increasing (non-decreasing allows equals)
