Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are given an array of integers nums. Some values in nums are missing and are denoted by -1.
You must choose a pair of positive integers (x, y) exactly once and replace each missing element with either x or y.
You need to minimize the maximum absolute difference between adjacent elements of nums after replacements.
Return the minimum possible difference.
Example 1:
Input: nums = [1,2,-1,10,8]
Output: 4
Explanation:
By choosing the pair as (6, 7), nums can be changed to [1, 2, 6, 10, 8].
The absolute differences between adjacent elements are:
|1 - 2| == 1|2 - 6| == 4|6 - 10| == 4|10 - 8| == 2Example 2:
Input: nums = [-1,-1,-1]
Output: 0
Explanation:
By choosing the pair as (4, 4), nums can be changed to [4, 4, 4].
Example 3:
Input: nums = [-1,10,-1,8]
Output: 1
Explanation:
By choosing the pair as (11, 9), nums can be changed to [11, 10, 9, 8].
Constraints:
2 <= nums.length <= 105nums[i] is either -1 or in the range [1, 109].Problem summary: You are given an array of integers nums. Some values in nums are missing and are denoted by -1. You must choose a pair of positive integers (x, y) exactly once and replace each missing element with either x or y. You need to minimize the maximum absolute difference between adjacent elements of nums after replacements. Return the minimum possible difference.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Binary Search · Greedy
[1,2,-1,10,8]
[-1,-1,-1]
[-1,10,-1,8]
minimum-absolute-sum-difference)minimize-the-maximum-adjacent-element-difference)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
class Solution {
public int minDifference(int[] nums) {
int maxPositiveGap = 0;
int mn = 1_000_000_000;
int mx = 0;
for (int i = 1; i < nums.length; ++i) {
if ((nums[i - 1] == -1) != (nums[i] == -1)) {
final int positive = Math.max(nums[i - 1], nums[i]);
mn = Math.min(mn, positive);
mx = Math.max(mx, positive);
} else {
maxPositiveGap = Math.max(maxPositiveGap, Math.abs(nums[i - 1] - nums[i]));
}
}
int l = maxPositiveGap;
int r = (mx - mn + 1) / 2;
while (l < r) {
final int m = (l + r) / 2;
if (check(nums, m, mn + m, mx - m))
r = m;
else
l = m + 1;
}
return l;
}
// Returns true if it's possible have `m` as maximum absolute difference
// between adjacent numbers, where -1s are replaced with `x` or `y`.
private boolean check(int[] nums, int m, int x, int y) {
int gapLength = 0;
int prev = 0;
for (final int num : nums) {
if (num == -1) {
++gapLength;
continue;
}
if (prev > 0 && gapLength > 0) {
if (gapLength == 1 && !checkSingleGap(prev, num, m, x, y))
return false;
if (gapLength > 1 && !checkMultipleGaps(prev, num, m, x, y))
return false;
}
prev = num;
gapLength = 0;
}
// Check leading gaps
if (nums[0] == -1) {
final int num = findFirstNumber(nums, 0, 1);
if (num != -1 && !checkBoundaryGaps(num, m, x, y))
return false;
}
// Check trailing gaps
if (nums[nums.length - 1] == -1) {
final int num = findFirstNumber(nums, nums.length - 1, -1);
if (num != -1 && !checkBoundaryGaps(num, m, x, y))
return false;
}
return true;
}
// Returns true if it's possible to have at most `m` as the minimized maximum
// difference for a sequence with a single -1 between two numbers.
// e.g. [a, -1, b] can be filled with either x or y.
private boolean checkSingleGap(int a, int b, int m, int x, int y) {
final int gapWithX = Math.max(Math.abs(a - x), Math.abs(b - x)); // [a, x, b]
final int gapWithY = Math.max(Math.abs(a - y), Math.abs(b - y)); // [a, y, b]
return Math.min(gapWithX, gapWithY) <= m;
}
// Returns true if it's possible to have at most `m` as the minimized maximum
// difference for a sequence with multiple -1s between two numbers.
// e.g. [a, -1, -1, ..., -1, b] can be filled with x and y.
private boolean checkMultipleGaps(int a, int b, int m, int x, int y) {
final int ax = Math.abs(a - x);
final int ay = Math.abs(a - y);
final int bx = Math.abs(b - x);
final int by = Math.abs(b - y);
final int xy = Math.abs(x - y);
final int gapAllX = Math.max(ax, bx); // [a, x, x, ..., x, b]
final int gapAllY = Math.max(ay, by); // [a, y, y, ..., y, b]
final int gapXToY = Math.max(Math.max(ax, xy), by); // [a, x, ..., y, b]
final int gapYToX = Math.max(Math.max(ay, xy), bx); // [a, y, ..., x, b]
return Math.min(Math.min(gapAllX, gapAllY), Math.min(gapXToY, gapYToX)) <= m;
}
// Returns true if it's possible to have at most `m` as the minimized maximum
// difference for a boundary sequence starting or ending with -1s.
// e.g. [a, -1, -1, ...] or [..., -1, -1, a].
private boolean checkBoundaryGaps(int a, int m, int x, int y) {
final int gapAllX = Math.abs(a - x); // [x, x, ..., x, a]
final int gapAllY = Math.abs(a - y); // [y, y, ..., y, a]
return Math.min(gapAllX, gapAllY) <= m;
}
// Returns the first positive number starting from the given index or -1
// if not found.
private int findFirstNumber(int[] nums, int start, int step) {
int i = start;
while (i >= 0 && i < nums.length && nums[i] == -1)
i += step;
return i >= 0 && i < nums.length ? nums[i] : -1;
}
}
// Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
package main
import "math"
// https://space.bilibili.com/206214
func minDifference(nums []int) (ans int) {
// 和空位相邻的最小数字 minL 和最大数字 maxR
minL, maxR := math.MaxInt, 0
for i, v := range nums {
if v != -1 && (i > 0 && nums[i-1] == -1 || i < len(nums)-1 && nums[i+1] == -1) {
minL = min(minL, v)
maxR = max(maxR, v)
}
}
preI := -1
for i, v := range nums {
if v == -1 {
continue
}
if preI >= 0 {
if i-preI == 1 {
ans = max(ans, abs(v-nums[preI]))
} else {
l, r := min(nums[preI], v), max(nums[preI], v)
d := (min(r-minL, maxR-l) + 1) / 2
if i-preI > 2 {
d = min(d, (maxR-minL+2)/3) // d 不能超过上界
}
ans = max(ans, d)
}
}
preI = i
}
return
}
func abs(x int) int { if x < 0 { return -x }; return x }
# Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
class Solution:
def minDifference(self, nums: list[int]) -> int:
maxPositiveGap = 0
mn = 1_000_000_000
mx = 0
for a, b in itertools.pairwise(nums):
if (a == -1) != (b == -1):
positive = max(a, b)
mn = min(mn, positive)
mx = max(mx, positive)
else:
maxPositiveGap = max(maxPositiveGap, abs(a - b))
l = maxPositiveGap
r = (mx - mn + 1) // 2
return bisect.bisect_left(
range(l, r), True,
key=lambda m: self._check(nums, m, mn + m, mx - m)) + l
def _check(self, nums: list[int], m: int, x: int, y: int) -> bool:
"""
Returns True if it's possible have `m` as maximum absolute difference
between adjacent numbers, where -1s are replaced with `x` or `y`.
"""
gapLength = 0
prev = 0
for num in nums:
if num == -1:
gapLength += 1
continue
if prev > 0 and gapLength > 0:
if gapLength == 1 and not self._checkSingleGap(prev, num, m, x, y):
return False
if gapLength > 1 and not self._checkMultipleGaps(prev, num, m, x, y):
return False
prev = num
gapLength = 0
# Check leading gaps
if nums[0] == -1:
num = next((num for num in nums if num != -1), -1)
if num != -1 and not self._checkBoundaryGaps(num, m, x, y):
return False
# Check trailing gaps
if nums[-1] == -1:
num = next((num for num in reversed(nums) if num != -1), -1)
if num != -1 and not self._checkBoundaryGaps(num, m, x, y):
return False
return True
def _checkSingleGap(self, a: int, b: int, m: int, x: int, y: int) -> bool:
"""
Returns true if it's possible to have at most `m` as the minimized maximum
difference for a sequence with a single -1 between two numbers.
e.g. [a, -1, b] can be filled with either x or y.
"""
gapWithX = max(abs(a - x), abs(b - x)) # [a, x, b]
gapWithY = max(abs(a - y), abs(b - y)) # [a, y, b]
return min(gapWithX, gapWithY) <= m
def _checkMultipleGaps(self, a: int, b: int, m: int, x: int, y: int) -> bool:
"""
Returns true if it's possible to have at most `m` as the minimized maximum
difference for a sequence with multiple -1s between two numbers.
e.g. [a, -1, -1, ..., -1, b] can be filled with x and y.
"""
ax = abs(a - x)
ay = abs(a - y)
bx = abs(b - x)
by = abs(b - y)
xy = abs(x - y)
gapAllX = max(ax, bx) # [a, x, x, ..., x, b]
gapAllY = max(ay, by) # [a, y, y, ..., y, b]
gapXToY = max(ax, xy, by) # [a, x, ..., y, b]
gapYToX = max(ay, xy, bx) # [a, y, ..., x, b]
return min(gapAllX, gapAllY, gapXToY, gapYToX) <= m
def _checkBoundaryGaps(self, a: int, m: int, x: int, y: int) -> bool:
"""
Returns true if it's possible to have at most `m` as the minimized maximum
difference for a boundary sequence starting or ending with -1s.
e.g. [a, -1, -1, ...] or [..., -1, -1, a].
"""
gapAllX = abs(a - x) # [x, x, ..., x, a]
gapAllY = abs(a - y) # [y, y, ..., y, a]
return min(gapAllX, gapAllY) <= m
// Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
// class Solution {
// public int minDifference(int[] nums) {
// int maxPositiveGap = 0;
// int mn = 1_000_000_000;
// int mx = 0;
//
// for (int i = 1; i < nums.length; ++i) {
// if ((nums[i - 1] == -1) != (nums[i] == -1)) {
// final int positive = Math.max(nums[i - 1], nums[i]);
// mn = Math.min(mn, positive);
// mx = Math.max(mx, positive);
// } else {
// maxPositiveGap = Math.max(maxPositiveGap, Math.abs(nums[i - 1] - nums[i]));
// }
// }
//
// int l = maxPositiveGap;
// int r = (mx - mn + 1) / 2;
//
// while (l < r) {
// final int m = (l + r) / 2;
// if (check(nums, m, mn + m, mx - m))
// r = m;
// else
// l = m + 1;
// }
//
// return l;
// }
//
// // Returns true if it's possible have `m` as maximum absolute difference
// // between adjacent numbers, where -1s are replaced with `x` or `y`.
// private boolean check(int[] nums, int m, int x, int y) {
// int gapLength = 0;
// int prev = 0;
//
// for (final int num : nums) {
// if (num == -1) {
// ++gapLength;
// continue;
// }
// if (prev > 0 && gapLength > 0) {
// if (gapLength == 1 && !checkSingleGap(prev, num, m, x, y))
// return false;
// if (gapLength > 1 && !checkMultipleGaps(prev, num, m, x, y))
// return false;
// }
// prev = num;
// gapLength = 0;
// }
//
// // Check leading gaps
// if (nums[0] == -1) {
// final int num = findFirstNumber(nums, 0, 1);
// if (num != -1 && !checkBoundaryGaps(num, m, x, y))
// return false;
// }
//
// // Check trailing gaps
// if (nums[nums.length - 1] == -1) {
// final int num = findFirstNumber(nums, nums.length - 1, -1);
// if (num != -1 && !checkBoundaryGaps(num, m, x, y))
// return false;
// }
//
// return true;
// }
//
// // Returns true if it's possible to have at most `m` as the minimized maximum
// // difference for a sequence with a single -1 between two numbers.
// // e.g. [a, -1, b] can be filled with either x or y.
// private boolean checkSingleGap(int a, int b, int m, int x, int y) {
// final int gapWithX = Math.max(Math.abs(a - x), Math.abs(b - x)); // [a, x, b]
// final int gapWithY = Math.max(Math.abs(a - y), Math.abs(b - y)); // [a, y, b]
// return Math.min(gapWithX, gapWithY) <= m;
// }
//
// // Returns true if it's possible to have at most `m` as the minimized maximum
// // difference for a sequence with multiple -1s between two numbers.
// // e.g. [a, -1, -1, ..., -1, b] can be filled with x and y.
// private boolean checkMultipleGaps(int a, int b, int m, int x, int y) {
// final int ax = Math.abs(a - x);
// final int ay = Math.abs(a - y);
// final int bx = Math.abs(b - x);
// final int by = Math.abs(b - y);
// final int xy = Math.abs(x - y);
// final int gapAllX = Math.max(ax, bx); // [a, x, x, ..., x, b]
// final int gapAllY = Math.max(ay, by); // [a, y, y, ..., y, b]
// final int gapXToY = Math.max(Math.max(ax, xy), by); // [a, x, ..., y, b]
// final int gapYToX = Math.max(Math.max(ay, xy), bx); // [a, y, ..., x, b]
// return Math.min(Math.min(gapAllX, gapAllY), Math.min(gapXToY, gapYToX)) <= m;
// }
//
// // Returns true if it's possible to have at most `m` as the minimized maximum
// // difference for a boundary sequence starting or ending with -1s.
// // e.g. [a, -1, -1, ...] or [..., -1, -1, a].
// private boolean checkBoundaryGaps(int a, int m, int x, int y) {
// final int gapAllX = Math.abs(a - x); // [x, x, ..., x, a]
// final int gapAllY = Math.abs(a - y); // [y, y, ..., y, a]
// return Math.min(gapAllX, gapAllY) <= m;
// }
//
// // Returns the first positive number starting from the given index or -1
// // if not found.
// private int findFirstNumber(int[] nums, int start, int step) {
// int i = start;
// while (i >= 0 && i < nums.length && nums[i] == -1)
// i += step;
// return i >= 0 && i < nums.length ? nums[i] : -1;
// }
// }
// Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #3357: Minimize the Maximum Adjacent Element Difference
// class Solution {
// public int minDifference(int[] nums) {
// int maxPositiveGap = 0;
// int mn = 1_000_000_000;
// int mx = 0;
//
// for (int i = 1; i < nums.length; ++i) {
// if ((nums[i - 1] == -1) != (nums[i] == -1)) {
// final int positive = Math.max(nums[i - 1], nums[i]);
// mn = Math.min(mn, positive);
// mx = Math.max(mx, positive);
// } else {
// maxPositiveGap = Math.max(maxPositiveGap, Math.abs(nums[i - 1] - nums[i]));
// }
// }
//
// int l = maxPositiveGap;
// int r = (mx - mn + 1) / 2;
//
// while (l < r) {
// final int m = (l + r) / 2;
// if (check(nums, m, mn + m, mx - m))
// r = m;
// else
// l = m + 1;
// }
//
// return l;
// }
//
// // Returns true if it's possible have `m` as maximum absolute difference
// // between adjacent numbers, where -1s are replaced with `x` or `y`.
// private boolean check(int[] nums, int m, int x, int y) {
// int gapLength = 0;
// int prev = 0;
//
// for (final int num : nums) {
// if (num == -1) {
// ++gapLength;
// continue;
// }
// if (prev > 0 && gapLength > 0) {
// if (gapLength == 1 && !checkSingleGap(prev, num, m, x, y))
// return false;
// if (gapLength > 1 && !checkMultipleGaps(prev, num, m, x, y))
// return false;
// }
// prev = num;
// gapLength = 0;
// }
//
// // Check leading gaps
// if (nums[0] == -1) {
// final int num = findFirstNumber(nums, 0, 1);
// if (num != -1 && !checkBoundaryGaps(num, m, x, y))
// return false;
// }
//
// // Check trailing gaps
// if (nums[nums.length - 1] == -1) {
// final int num = findFirstNumber(nums, nums.length - 1, -1);
// if (num != -1 && !checkBoundaryGaps(num, m, x, y))
// return false;
// }
//
// return true;
// }
//
// // Returns true if it's possible to have at most `m` as the minimized maximum
// // difference for a sequence with a single -1 between two numbers.
// // e.g. [a, -1, b] can be filled with either x or y.
// private boolean checkSingleGap(int a, int b, int m, int x, int y) {
// final int gapWithX = Math.max(Math.abs(a - x), Math.abs(b - x)); // [a, x, b]
// final int gapWithY = Math.max(Math.abs(a - y), Math.abs(b - y)); // [a, y, b]
// return Math.min(gapWithX, gapWithY) <= m;
// }
//
// // Returns true if it's possible to have at most `m` as the minimized maximum
// // difference for a sequence with multiple -1s between two numbers.
// // e.g. [a, -1, -1, ..., -1, b] can be filled with x and y.
// private boolean checkMultipleGaps(int a, int b, int m, int x, int y) {
// final int ax = Math.abs(a - x);
// final int ay = Math.abs(a - y);
// final int bx = Math.abs(b - x);
// final int by = Math.abs(b - y);
// final int xy = Math.abs(x - y);
// final int gapAllX = Math.max(ax, bx); // [a, x, x, ..., x, b]
// final int gapAllY = Math.max(ay, by); // [a, y, y, ..., y, b]
// final int gapXToY = Math.max(Math.max(ax, xy), by); // [a, x, ..., y, b]
// final int gapYToX = Math.max(Math.max(ay, xy), bx); // [a, y, ..., x, b]
// return Math.min(Math.min(gapAllX, gapAllY), Math.min(gapXToY, gapYToX)) <= m;
// }
//
// // Returns true if it's possible to have at most `m` as the minimized maximum
// // difference for a boundary sequence starting or ending with -1s.
// // e.g. [a, -1, -1, ...] or [..., -1, -1, a].
// private boolean checkBoundaryGaps(int a, int m, int x, int y) {
// final int gapAllX = Math.abs(a - x); // [x, x, ..., x, a]
// final int gapAllY = Math.abs(a - y); // [y, y, ..., y, a]
// return Math.min(gapAllX, gapAllY) <= m;
// }
//
// // Returns the first positive number starting from the given index or -1
// // if not found.
// private int findFirstNumber(int[] nums, int start, int step) {
// int i = start;
// while (i >= 0 && i < nums.length && nums[i] == -1)
// i += step;
// return i >= 0 && i < nums.length ? nums[i] : -1;
// }
// }
Use this to step through a reusable interview workflow for this problem.
Check every element from left to right until we find the target or exhaust the array. Each comparison is O(1), and we may visit all n elements, giving O(n). No extra space needed.
Each comparison eliminates half the remaining search space. After k comparisons, the space is n/2ᵏ. We stop when the space is 1, so k = log₂ n. No extra memory needed — just two pointers (lo, hi).
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.
Wrong move: Locally optimal choices may fail globally.
Usually fails on: Counterexamples appear on crafted input orderings.
Fix: Verify with exchange argument or monotonic objective before committing.