I felt like doing an algorithm and found this problem on leetcode
Given an array of integers, find two numbers such that they add up to a specific target num
The naïve solution to the two-sum problem is O(n^2)
, s.t. n
is the length of the array of numbers provided.
However, we can do better by using a hash-map of the values seen so far (key=number, value=index) and checking if the complement is already there (O(1)
) as we iterate over the numbers. This approach is optimal for an unsorted array:
O(n)
O(n)
-- though if there is a solution, in practice this would be O(n/2)
Given the OP's question:
O(n)
) or time (O(n)
), depending on the approach chosen. Therefore, the 1st part of the (currently) accepted solution is, strictly speaking, incorrect.Optimal solution:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
seen = {}
for j, num in enumerate(nums):
i = seen.get(target-num, -1)
if i != -1:
return [i+1, j+1]
seen[num] = j
return [-1, -1]
import java.util.Map;
import java.util.HashMap;
public class Solution {
public int[] twoSum(int[] nums, int target) {
final Map seen = new HashMap<>();
for (int j = 0; j < nums.length; ++j) {
final Integer i = seen.get(target - nums[j]); // One hash-map access v.s. two when using contains beforehand.
if (i != null) {
return new int[]{ i+1, j+1 };
}
numbers.put(nums[j], j);
}
return new int[]{-1, -1};
}
}
Note that by construction, if the complement is present in the map/dictionary, then the index stored will always be lower than the current index. Hence the following proposition is verified:
index1 must be less than index2
Also note that the OP's question needed 1-based indexes, which is what I've provided above, but the Leetcode question referred to seems to have been updated since then, and now is 0-based: https://leetcode.com/problems/two-sum.
I hope this helps.