twoSum Algorithm : How to improve this?

前端 未结 22 2366
礼貌的吻别
礼貌的吻别 2021-02-06 01:38

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

22条回答
  •  耶瑟儿~
    2021-02-06 01:48

    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:

    • Runtime complexity: O(n)
    • Space complexity: O(n) -- though if there is a solution, in practice this would be O(n/2)

    Given the OP's question:

    • does not specify whether the input array is sorted or not (it is, therefore, safe to assume the input array can be anything), and
    • specifically asks for indexes of the provided array, as opposed to the actual numbers, any kind of solution sorting the array would need to copy it beforehand, keep a mapping of indexes between the sorted array and the unsorted one, or iterate over the original array, hence costing memory (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:

    • In Python:
    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]
    
    • In Java:
    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.

提交回复
热议问题