Can you suggest an algorithm that find all pairs of nodes in a link list that add up to 10.
I came up with the following.
Algorithm: Compare each node, starting with the second node, with each node starting from the head node till the previous node (previous to the current node being compared) and report all such pairs.
I think this algorithm should work however its certainly not the most efficient one having a complexity of O(n2).
Can anyone hint at a solution which is more efficient (perhaps takes linear time). Additional or temporary nodes can be used by such a solution.
If their range is limited (say between -100 and 100), it’s easy.
Create an array
quant[-100..100]then just cycle through your linked list, executing:Then the following loop will do the trick.
Even if their range isn’t limited, you can have a more efficient method than what you proposed, by sorting the values first and then just keeping counts rather than individual values (same as the above solution).
This is achieved by running two pointers, one at the start of the list and one at the end. When the numbers at those pointers add up to 10, output them and move the end pointer down and the start pointer up.
When they’re greater than 10, move the end pointer down. When they’re less, move the start pointer up.
This relies on the sorted nature. Less than 10 means you need to make the sum higher (move start pointer up). Greater than 10 means you need to make the sum less (end pointer down). Since they’re are no duplicates in the list (because of the counts), being equal to 10 means you move both pointers.
Stop when the pointers pass each other.
There’s one more tricky bit and that’s when the pointers are equal and the value sums to 10 (this can only happen when the value is 5, obviously).
You don’t output the number of pairs based on the product, rather it’s based on the product of the value minus 1. That’s because a value 5 with count of 1 doesn’t actually sum to 10 (since there’s only one 5).
So, for the list:
you get:
p1ataandp2ath. Since-1 + 11 = 10, you output those two numbers (as above, you do itNtimes whereNis the product of the counts). Thats one copy of(-1,11). Then you movep1tobandp2tog.1 + 10 > 10so leavep1atb, movep2down tof.1 + 7 < 10so movep1toc, leavep2atf.2 + 7 < 10so movep1tod, leavep2atf.3 + 7 = 10, output two copies of(3,7)since the count ofdis 2, movep1toe,p2toe.5 + 5 = 10butp1 = p2so the product is 0 times 0 or 0. Output nothing, movep1tof,p2tod.p1 > p2.Hence the overall output was:
which is correct.
Here’s some test code. You’ll notice that I’ve forced 7 (the midpoint) to a specific value for testing. Obviously, you wouldn’t do this.
You’ll see that the code above is all O(n) since I’m not sorting in this version, just intelligently using the values as indexes.
If the minimum is below zero (or very high to the point where it would waste too much memory), you can just use a minVal to adjust the indexes (another O(n) scan to find the minimum value and then just use
i-minValinstead ofifor array indexes).And, even if the range from low to high is too expensive on memory, you can use a sparse array. You’ll have to sort it, O(n log n), and search it for updating counts, also O(n log n), but that’s still better than the original O(n2). The reason the binary search is O(n log n) is because a single search would be O(log n) but you have to do it for each value.
And here’s the output from a test run, which shows you the various stages of calculation.