Description
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
Solution_1
最简单直接的方法,即:
① 利用二重循环依次遍历数组中的二元组,并累和以判定是否与Target相等。
② 若相等,依次输出该二元对元素的下标,算法结束。
③ 若不相等,重复①过程。
整个算法的时间复杂度为O(n²),其运行时长为106ms。
Solution_2
不难发现,解决问题的核心在于:对数组中任一元素,如何快速的在数组中检索该元素相对于Target的补是否存在。
为了加速这一查询,引入与之相适应的哈希表数据结构。在C++的标准函数库中对map已有完整的实现。
整个算法的思路如下:
① 对nums数组进行遍历,并在插入哈希表前,判断其补在哈希表中是否已经存在。
② 若存在,依次输出哈希表中与补相对应的值以及当前元素的下标,算法结束。
③ 若不存在,以元素值为键,下标为值,即<元素值,下标>的键值对形式插入哈希表,并重复①过程。
其精妙之处在于可以避免对重复元素的情况做特殊处理,举例如下:
对于输入:[3, 3, 1] Target:6
该算法不需要考虑map中键须独一无二的情况,因为在遍历第二个元素时,其在插入哈希表前就检索其补“3”在当前表中是否存在。
整个算法的时间复杂度为O(n),其运行时长为12ms。
Solution_3
两个数累加得到target,必然有一个数大于等于target/2,有一个数小于等于target/2。
这意味着如果数组是有序的,则只需要对数组中的部分元素进行检查而非全部。
但前提是数组有序,所以排序的预处理将占据O(nlogn)的时间复杂度。
存在的问题是排序会打乱数据原有的下标,所以需要将nums转入map容器,但会产生部分重复数据的问题,即[3, 3],target为6的输入情况。
如果改用multimap数据结构,将不再能简单的依据键值对通过[]操作符进行索引。
由于一个数据最多重复两次,故采用的解决方法是采用双map,对于map1中已存在的数据,存入map2以供检索。
整个算法的思路如下:
① 采用双map对nums中的数据进行存入。
② 对nums中的数据进行排序。
③ 以小于等于target/2为循环结束条件,从最小元素开始遍历。
④ 若当前元素的补在map1或map2中存在:
⑤ 若元素与补值不相同,则返回当前元素值与补值的下标索引,算法结束。
⑥ 若当前元素值与补值相同,检查map2是否存在补值,若存在,返回下标,算法结束;若不存在,返回③。
整个算法的时间复杂度为O(nlogn),其运行时长为9ms。
虽然还减少了3ms,但该算法逻辑上不直接,实现不简洁,只能说是比较适应题目的测试集合,所以第二种方案是目前最理想的解题思路。