LeetCode - 两数之和

LeeetCode题目网址:https://leetcodechina.com/problems/two-sum/description/

题目描述:

给定一个整数数列,找出其中和为特定值的那两个数。
你可以假设每个输入都只会有一种答案,同样的元素不能被重用。

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

https://github.com/biezhihua/LeetCode

题目思路:

仔细的阅读题目获取有效信息。

  1. 信息1:从“给定一个整数数列”可以得知,预先给的数组可能是无序状态。
  2. 信息2:从“和为特定值的两个数”可以得知,预先给一个Target值,让们找出该无序数组中是否存在两数其和为Target。
  3. 信息3:再根据示例要求返回该无序数组中两数的索引值,可以知道在该题目中无法使用先排序的解法,因为排序会导致元素从排,同时索引会被打断。
  4. 信息4:两数之和结果唯一,且不能重用同一个数。

思路1:
先确定两数中的一个数,再去确定另外一个数,然后判断两数之和与Target的关系。该解法需要两层for循环,第一个for循环用于确定第一个数,第二个for循环用于确定第二个数,然后在最内部做逻辑判断。

虽然此法简单,但是时间复杂度是 O(n2) O ( n 2 ) 。显然不是最优解法。(谁都能直接想到的解法往往都不是最优解法)。

思路2:

在思路1中“先确定一个数再确定另一个数”显然不是我们继续思考的方向了,因为一次for能确定一个数和索引,那么能不能在确定索引的同时确定另外一个数的索引呢?也就是如何同时表示两个维度的信息(也就是两个数的信息)。

哈希表 - Map可以同时存储两种信息,并让其对应起来。
数组也可以看做一个哈希表,其索引和数值一一对应,a[i] = value;

我们可以在Map中将当前数与Target值得差值作为Key,将当前数的索引作为Value。这样就同时表示了两个维度的信息,Key代表我们对另外一个数的要求,Value代表当前数的索引。

举个例子,Target为9,当前索引为0数为2,那么差值为7。只要后面数组中存在数值为7,那么两者和就为Target。

该思路的核心在于如何在一次操作中确定两个数的信息。这样遍历一遍就能得到结果,其时间复杂度为 O(n) O ( n )

题目解法:

public class Code_3_4_TwoSum {

    @Test
    public void test() {
        int[] nums = new int[]{2, 7, 11, 15};
        Assert.assertArrayEquals(new int[]{0, 1}, twoSum(nums, 9));
        Assert.assertArrayEquals(new int[]{-1, -1}, twoSum(nums, 10));
    }

    int[] twoSum(int[] nums, int target) {
        int[] rs = new int[]{-1, -1};

        if (nums == null || nums.length <= 1)
            return rs;

        Map hashMap = new HashMap<>();

        for (int i = 0; i < nums.length; i++) {
            if (hashMap.containsKey(nums[i])) {
                rs[0] = hashMap.get(nums[i]);
                rs[1] = i;
                return rs;
            } else {
                hashMap.put(target - nums[i], i);
            }
        }

        return rs;
    }
}

你可能感兴趣的:(LeetCode,消灭LeetCode)