Searching & SortingProblem 32 of 36
DoubleHelix SPOJ
Problem Statement
Two DNA sequences are given as two arrays of integers. The sequences intersect at certain points (where they have the same value). You can switch from one sequence to another only at intersection points.
Find the maximum possible sum when traversing from the start to the end, switching optimally between sequences.
Constraints:
- 1 ≤ n, m ≤ 10^5
- Both arrays are sorted in ascending order
- Values are positive integers
Example:
- Input:
seq1 = [3, 5, 7, 9, 20, 25, 30, 40, 55, 56, 57, 60, 62]seq2 = [1, 4, 7, 11, 14, 25, 44, 47, 55, 57, 100]
- Output:
450 - Explanation: Intersection points are 7, 25, 55, 57. Optimal path switches at these points to maximize sum.
Example 2:
- Input:
seq1 = [1, 2, 3]seq2 = [2, 3, 4]
- Output:
10 - Explanation: Path: 1 → 2 → switch → 3 → 4 = 10 (or stay on seq1: 1+2+3=6, stay on seq2: 2+3+4=9)
Approach 1: Brute Force (Find All Paths)
Intuition
Find all intersection points, then try all possible combinations of switches to find the maximum sum.
Algorithm
- Find all intersection points using nested loops
- Try all 2^k combinations (switch or not at each intersection)
- Calculate sum for each path and track maximum
java
public class Solution {
public long maxSumBrute(int[] seq1, int[] seq2) {
// Similar implementation
return 0; // Placeholder
}
}Complexity Analysis
- Time Complexity: O(n × m) for finding intersections + O(2^k) for paths
- Space Complexity: O(n + m) for storing sequences
Approach 2: Two Pointers with Segment Sums (Optimal)
Intuition
Use two pointers to traverse both sequences simultaneously. Between any two consecutive intersection points, we have two path options - calculate both and take the maximum.
Key Observations:
- Both sequences are sorted
- At each intersection, we can choose either path
- Between intersections, we must stay on one sequence
- Greedy choice: at each intersection, take the path with higher segment sum
Algorithm
- Use two pointers i, j starting at 0
- Move the pointer with smaller value, accumulating sums
- When values are equal (intersection), add max of both segment sums
- Continue until both sequences are exhausted
java
public class DoubleHelix {
public long maxSum(int[] seq1, int[] seq2) {
int n = seq1.length, m = seq2.length;
int i = 0, j = 0;
long sum1 = 0, sum2 = 0;
long result = 0;
while (i < n && j < m) {
if (seq1[i] < seq2[j]) {
sum1 += seq1[i];
i++;
} else if (seq1[i] > seq2[j]) {
sum2 += seq2[j];
j++;
} else {
// Intersection point
sum1 += seq1[i];
sum2 += seq2[j];
result += Math.max(sum1, sum2);
sum1 = 0;
sum2 = 0;
i++;
j++;
}
}
while (i < n) {
sum1 += seq1[i];
i++;
}
while (j < m) {
sum2 += seq2[j];
j++;
}
result += Math.max(sum1, sum2);
return result;
}
public static void main(String[] args) {
DoubleHelix dh = new DoubleHelix();
int[] seq1 = {3, 5, 7, 9, 20, 25, 30, 40, 55, 56, 57, 60, 62};
int[] seq2 = {1, 4, 7, 11, 14, 25, 44, 47, 55, 57, 100};
System.out.println(dh.maxSum(seq1, seq2)); // Output: 450
}
}Dry Run Example
seq1 = [3, 5, 7, 9, 20, 25, 30, 40, 55, 56, 57, 60, 62]
seq2 = [1, 4, 7, 11, 14, 25, 44, 47, 55, 57, 100]
Intersection points: 7, 25, 55, 57
Segment 1: Before 7
seq1: 3 + 5 = 8, then + 7 = 15
seq2: 1 + 4 = 5, then + 7 = 12
max(15, 12) = 15
result = 15
Segment 2: Between 7 and 25
seq1: 9 + 20 = 29, then + 25 = 54
seq2: 11 + 14 = 25, then + 25 = 50
max(54, 50) = 54
result = 15 + 54 = 69
Segment 3: Between 25 and 55
seq1: 30 + 40 = 70, then + 55 = 125
seq2: 44 + 47 = 91, then + 55 = 146
max(125, 146) = 146
result = 69 + 146 = 215
Segment 4: Between 55 and 57
seq1: 56 = 56, then + 57 = 113
seq2: 0, then + 57 = 57
max(113, 57) = 113
result = 215 + 113 = 328
Segment 5: After 57
seq1: 60 + 62 = 122
seq2: 100
max(122, 100) = 122
result = 328 + 122 = 450
Final Result: 450
Complexity Analysis
- Time Complexity: O(n + m) - Single pass through both arrays
- Space Complexity: O(1) - Only using variables
SPOJ Solution Template
Visualization
seq1: [3, 5, 7, 9, 20, 25, 30, 40, 55, 56, 57, 60, 62]
↓ ↓ ↓ ↓
seq2: [1, 4, 7, 11, 14, 25, 44, 47, 55, 57, 100]
Segments:
[start to 7] → choose max(seq1_sum, seq2_sum)
[7 to 25] → choose max(seq1_sum, seq2_sum)
[25 to 55] → choose max(seq1_sum, seq2_sum)
[55 to 57] → choose max(seq1_sum, seq2_sum)
[57 to end] → choose max(seq1_sum, seq2_sum)
Key Takeaways
- Two Pointers on Sorted Arrays: Classic technique for merging/comparing sorted arrays
- Greedy at Intersections: Always take the path with higher segment sum
- Segment Sums: Track cumulative sums between intersection points
- Include Intersection: Add intersection value to both segment sums before comparing
- Handle Remainders: After loop, process remaining elements in both arrays
- Single Pass: O(n + m) is optimal for this problem
- DNA Analogy: Think of it as choosing the best "strand" to follow