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 two sorted arrays of distinct integers nums1 and nums2.
A valid path is defined as follows:
nums1 or nums2 to traverse (from index-0).nums1 and nums2 you are allowed to change your path to the other array. (Only one repeated value is considered in the valid path).The score is defined as the sum of unique values in a valid path.
Return the maximum score you can obtain of all possible valid paths. Since the answer may be too large, return it modulo 109 + 7.
Example 1:
Input: nums1 = [2,4,5,8,10], nums2 = [4,6,8,9] Output: 30 Explanation: Valid paths: [2,4,5,8,10], [2,4,5,8,9], [2,4,6,8,9], [2,4,6,8,10], (starting from nums1) [4,6,8,9], [4,5,8,10], [4,5,8,9], [4,6,8,10] (starting from nums2) The maximum is obtained with the path in green [2,4,6,8,10].
Example 2:
Input: nums1 = [1,3,5,7,9], nums2 = [3,5,100] Output: 109 Explanation: Maximum sum is obtained with the path [1,3,5,100].
Example 3:
Input: nums1 = [1,2,3,4,5], nums2 = [6,7,8,9,10] Output: 40 Explanation: There are no common elements between nums1 and nums2. Maximum sum is obtained with the path [6,7,8,9,10].
Constraints:
1 <= nums1.length, nums2.length <= 1051 <= nums1[i], nums2[i] <= 107nums1 and nums2 are strictly increasing.Problem summary: You are given two sorted arrays of distinct integers nums1 and nums2. A valid path is defined as follows: Choose array nums1 or nums2 to traverse (from index-0). Traverse the current array from left to right. If you are reading any value that is present in nums1 and nums2 you are allowed to change your path to the other array. (Only one repeated value is considered in the valid path). The score is defined as the sum of unique values in a valid path. Return the maximum score you can obtain of all possible valid paths. Since the answer may be too large, return it modulo 109 + 7.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Two Pointers · Dynamic Programming · Greedy
[2,4,5,8,10] [4,6,8,9]
[1,3,5,7,9] [3,5,100]
[1,2,3,4,5] [6,7,8,9,10]
maximum-score-of-a-node-sequence)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1537: Get the Maximum Score
class Solution {
public int maxSum(int[] nums1, int[] nums2) {
final int mod = (int) 1e9 + 7;
int m = nums1.length, n = nums2.length;
int i = 0, j = 0;
long f = 0, g = 0;
while (i < m || j < n) {
if (i == m) {
g += nums2[j++];
} else if (j == n) {
f += nums1[i++];
} else if (nums1[i] < nums2[j]) {
f += nums1[i++];
} else if (nums1[i] > nums2[j]) {
g += nums2[j++];
} else {
f = g = Math.max(f, g) + nums1[i];
i++;
j++;
}
}
return (int) (Math.max(f, g) % mod);
}
}
// Accepted solution for LeetCode #1537: Get the Maximum Score
func maxSum(nums1 []int, nums2 []int) int {
const mod int = 1e9 + 7
m, n := len(nums1), len(nums2)
i, j := 0, 0
f, g := 0, 0
for i < m || j < n {
if i == m {
g += nums2[j]
j++
} else if j == n {
f += nums1[i]
i++
} else if nums1[i] < nums2[j] {
f += nums1[i]
i++
} else if nums1[i] > nums2[j] {
g += nums2[j]
j++
} else {
f = max(f, g) + nums1[i]
g = f
i++
j++
}
}
return max(f, g) % mod
}
# Accepted solution for LeetCode #1537: Get the Maximum Score
class Solution:
def maxSum(self, nums1: List[int], nums2: List[int]) -> int:
mod = 10**9 + 7
m, n = len(nums1), len(nums2)
i = j = 0
f = g = 0
while i < m or j < n:
if i == m:
g += nums2[j]
j += 1
elif j == n:
f += nums1[i]
i += 1
elif nums1[i] < nums2[j]:
f += nums1[i]
i += 1
elif nums1[i] > nums2[j]:
g += nums2[j]
j += 1
else:
f = g = max(f, g) + nums1[i]
i += 1
j += 1
return max(f, g) % mod
// Accepted solution for LeetCode #1537: Get the Maximum Score
struct Solution;
use std::collections::BTreeSet;
use std::collections::HashSet;
const MOD: i64 = 1_000_000_007;
impl Solution {
fn max_sum(nums1: Vec<i32>, nums2: Vec<i32>) -> i32 {
let set1: HashSet<i32> = nums1.iter().copied().collect();
let set2: HashSet<i32> = nums2.iter().copied().collect();
let all: BTreeSet<i32> = nums1.iter().copied().chain(nums2.iter().copied()).collect();
let mut prev1 = 0;
let mut prev2 = 0;
let mut res = 0;
for x in all {
if set1.contains(&x) {
prev1 += x as i64;
}
if set2.contains(&x) {
prev2 += x as i64;
}
if set1.contains(&x) && set2.contains(&x) {
let max = prev1.max(prev2);
prev1 = max;
prev2 = max;
}
res = res.max(prev1);
res = res.max(prev2);
}
res %= MOD;
res as i32
}
}
#[test]
fn test() {
let nums1 = vec![2, 4, 5, 8, 10];
let nums2 = vec![4, 6, 8, 9];
let res = 30;
assert_eq!(Solution::max_sum(nums1, nums2), res);
let nums1 = vec![1, 3, 5, 7, 9];
let nums2 = vec![3, 5, 100];
let res = 109;
assert_eq!(Solution::max_sum(nums1, nums2), res);
}
// Accepted solution for LeetCode #1537: Get the Maximum Score
function maxSum(nums1: number[], nums2: number[]): number {
const mod = 1e9 + 7;
const m = nums1.length;
const n = nums2.length;
let [f, g] = [0, 0];
let [i, j] = [0, 0];
while (i < m || j < n) {
if (i === m) {
g += nums2[j++];
} else if (j === n) {
f += nums1[i++];
} else if (nums1[i] < nums2[j]) {
f += nums1[i++];
} else if (nums1[i] > nums2[j]) {
g += nums2[j++];
} else {
f = g = Math.max(f, g) + nums1[i];
i++;
j++;
}
}
return Math.max(f, g) % mod;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair of elements. The outer loop picks one element, the inner loop scans the rest. For n elements that is n × (n−1)/2 comparisons = O(n²). No extra memory — just two loop variables.
Each pointer traverses the array at most once. With two pointers moving inward (or both moving right), the total number of steps is bounded by n. Each comparison is O(1), giving O(n) overall. No auxiliary data structures are needed — just two index variables.
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: Advancing both pointers shrinks the search space too aggressively and skips candidates.
Usually fails on: A valid pair can be skipped when only one side should move.
Fix: Move exactly one pointer per decision branch based on invariant.
Wrong move: An incomplete state merges distinct subproblems and caches incorrect answers.
Usually fails on: Correctness breaks on cases that differ only in hidden state.
Fix: Define state so each unique subproblem maps to one DP cell.
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.