[Leetcode] Two Sum 兩數和

Two Sum

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.java

You may assume that each input would have exactly one solution.數組

Input: numbers={2, 7, 11, 15}, target=9 Output: index1=1, index2=2less

暴力法 Brute Force

複雜度

O(1)空間 O(n^2)時間指針

思路

經過雙重循環遍歷數組中全部元素的兩兩組合,當出現符合的和時返回兩個元素的下標code

注意

  • 內層循環要從外層循環下標加一開始,避免遍歷到兩個相同的元素

代碼

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        if(nums.length < 2){
            return result;
        }
        for(int i = 0 ; i < nums.length; i++){
            for(int j = i + 1; j < nums.length; j++){
                if((nums[i]+nums[j])==target){
                    result[0] = i + 1;
                    result[1] = j + 1;
                    return result;
                }
            }
        }
        return result;
    }
}

哈希表 Hash Table

複雜度

O(n)空間 O(n)時間排序

思路

第一次遍歷數組先將全部元素和它的下標做爲key-value對存入Hashmap中,第二次遍歷數組時根據目標和與當前元素之差,在Hashmap中找相應的差值。若是存在該差值,說明存在兩個數之和是目標和。此時記錄下當前數組元素下標並拿出Hashmap中數組元素下標便可。Hashmap獲取元素的時間複雜度是O(1),因此總的時間複雜度仍不超過O(n)。ci

注意

  • 斷定是否存在該差值時,要同時判斷該差值的下標是否是當前遍歷的元素下標,以免重複
  • 哈希表做爲一個Collection,初始化時請注意聲明Key和Value的類型

代碼

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        int[] res = new int[2];
        for(int i = 0; i < nums.length; i++){
            int diff = target - nums[i];
            if(map.containsKey(nums[i])){
                res[0] = map.get(nums[i]) + 1;
                res[1] = i + 1;
            }
            map.put(diff, i);
        }
        return res;
    }
}

2018/2 更新get

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        numsMap = {}
        for index in range(0, len(nums)):
            num1 = nums[index]
            num2 = target - num1
            if num2 in numsMap:
                return [index, numsMap[num2]]
            else:
                numsMap[num1] = index

2018/10input

func twoSum(nums []int, target int) []int {
    m := make(map[int]int)
    result := make([]int, 2)

    for i := 0; i < len(nums); i++ {
        var curr = nums[i]
        var diff = target - curr
        result[0] = i
        if _, ok := m[diff]; ok {
            result[1] = m[diff]
            return result
        } else {
            m[curr] = i
        }
    }
    return result
}

排序雙指針法 Sorting with Two Pointers

複雜度

O(n)空間 O(nlogn)時間it

思路

首先將原數組複製一遍,對新數組進行排序。排序後將雙指針指向頭部與尾部元素,進行迭代。若是雙指針指向元素之和大於目標和,則將尾部指針向前移一位,反之則將頭部指針向後移一位,直到雙指針指向元素之和等於目標和,記錄這兩個元素的值,而後再遍歷一遍舊數組,找出這兩個元素的下標。

注意

  • 該方法須要先將結果數組都初始化爲-1,不然在遍歷舊數組時沒法去除重複,可能會將兩個下標都存入同一個結果中

代碼

private ArrayList<List<Integer>> twoSum(int[] nums, int target){
    int left = 0, right = nums.length - 1;
    ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
    while(left < right){
        if(nums[left] + nums[right] == target){
            ArrayList<Integer> curr = new ArrayList<Integer>();
            curr.add(nums[left]);
            curr.add(nums[right]);
            res.add(curr);
            do {
                left++;
            }while(left < nums.length && nums[left] == nums[left-1]);
            do {
                right--;
            } while(right >= 0 && nums[right] == nums[right+1]);
        } else if (nums[left] + nums[right] > target){
            right--;
        } else {
            left++;
        }
    }
    return res;
}

後續 Follow Up

Q:若是不須要返回數組下標,只用返回兩個數自己呢?
A:若是隻用返回兩個數自己,排序雙指針法能夠作到O(1)空間,時間複雜度還是O(nlogn)。而哈希表方法中的HashMap則能夠換成HashSet。

Q:若是要求的不是兩個數和和,而是找兩個數之差爲特定值的配對呢?A:一樣用哈希表能夠解決。若是要不用空間的話,也能夠先排序,而後將兩個指針指向頭,兩個數差小於目標時,將後指針向後移,不然將前指針向後移。

相關文章
相關標籤/搜索