Problem
Given an array of integers, find two numbers such that they add up to aspecific target number. The function twoSum should return indices of the two numbers such thatthey add up to the target, where index1 must be less than index2. Please notethat your returned answers (both index1 and index2) are NOT zero-based. Example
numbers=[, , , ], target= return [, ] Note
You may assume that each input would have exactly one solution Challenge
Either of the following solutions are acceptable: O(n) Space, O(nlogn) Time
O(n) Space, O(n) Time

题解1 - 哈希表

找两数之和是否为target, 如果是找数组中一个值为target该多好啊!遍历一次就知道了,我只想说,too naive... 难道要将数组中所有元素的两两组合都求出来与target比较吗?时间复杂度显然为 O(n2), 显然不符题目要求。找一个数时直接遍历即可,那么可不可以将两个数之和转换为找一个数呢?我们先来看看两数之和为target所对应的判断条件—— xi+xj=target, 可进一步转化为 xi=target−xj, 其中 i 和 j 为数组中的下标。一段神奇的数学推理就将找两数之和转化为了找一个数是否在数组中了!可见数学是多么的重要...

基本思路有了,现在就来看看怎么实现,显然我们需要额外的空间(也就是哈希表)来保存已经处理过的 xj(注意这里并不能先初始化哈希表,否则无法排除两个相同的元素相加为 target 的情况), 如果不满足等式条件,那么我们就往后遍历,并把之前的元素加入到哈希表中,如果target减去当前索引后的值在哈希表中找到了,那么就将哈希表中相应的索引返回,大功告成!

C++:

class Solution {
public:
/*
* @param numbers : An array of Integer
* @param target : target = numbers[index1] + numbers[index2]
* @return : [index1+1, index2+1] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target) {
vector<int> result;
const int length = nums.size();
if ( == length) {
return result;
} // first value, second index
unordered_map<int, int> hash(length);
for (int i = ; i != length; ++i) {
if (hash.find(target - nums[i]) != hash.end()) {
result.push_back(hash[target - nums[i]]);
result.push_back(i + );
return result;
} else {
hash[nums[i]] = i + ;
}
} return result;
}
};

JAVA:

public class Solution {
/*
* @param numbers : An array of Integer
* @param target : target = numbers[index1] + numbers[index2]
* @return : [index1 + 1, index2 + 1] (index1 < index2)
*/
public int[] twoSum(int[] numbers, int target) {
if (numbers == null || numbers.length == 0) return new int[]{0, 0}; Map<Integer, Integer> hashmap = new HashMap<Integer, Integer>();
int index1 = 0, index2 = 0;
for (int i = 0; i < numbers.length; i++) {
if (hashmap.containsKey(target - numbers[i])) {
index1 = hashmap.get(target - numbers[i]);
index2 = i;
return new int[]{1 + index1, 1 + index2};
} else {
hashmap.put(numbers[i], i);
}
} return new int[]{0, 0};
}
}

源码分析

  1. 异常处理。
  2. 使用 C++ 11 中的哈希表实现unordered_map映射值和索引。Python 中的dict就是天然的哈希表。
  3. 找到满足条件的解就返回,找不到就加入哈希表中。注意题中要求返回索引值的含义。

复杂度分析

哈希表用了和数组等长的空间,空间复杂度为 O(n), 遍历一次数组,时间复杂度为 O(n).

题解2 - 排序后使用两根指针

但凡可以用空间换时间的做法,往往也可以使用时间换空间。另外一个容易想到的思路就是先对数组排序,然后使用两根指针分别指向首尾元素,逐步向中间靠拢,直至找到满足条件的索引为止。

C++:

class Solution {
public:
/*
* @param numbers : An array of Integer
* @param target : target = numbers[index1] + numbers[index2]
* @return : [index1+1, index2+1] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target) {
vector<int> result;
const int length = nums.size();
if ( == length) {
return result;
} // first num, second is index
vector<pair<int, int> > num_index(length);
// map num value and index
for (int i = ; i != length; ++i) {
num_index[i].first = nums[i];
num_index[i].second = i + ;
} sort(num_index.begin(), num_index.end());
int start = , end = length - ;
while (start < end) {
if (num_index[start].first + num_index[end].first > target) {
--end;
} else if(num_index[start].first + num_index[end].first == target) {
int min_index = min(num_index[start].second, num_index[end].second);
int max_index = max(num_index[start].second, num_index[end].second);
result.push_back(min_index);
result.push_back(max_index);
return result;
} else {
++start;
}
} return result;
}
};

源码分析

  1. 异常处理。
  2. 使用length保存数组的长度,避免反复调用nums.size()造成性能损失。
  3. 使用pair组合排序前的值和索引,避免排序后找不到原有索引信息。
  4. 使用标准库函数排序。
  5. 两根指针指头尾,逐步靠拢。

复杂度分析

遍历一次原数组得到pair类型的新数组,时间复杂度为 O(n), 空间复杂度也为 O(n). 标准库中的排序方法时间复杂度近似为 O(nlogn), 两根指针遍历数组时间复杂度为 O(n).

2 Sum的更多相关文章

  1. LeetCode - Two Sum

    Two Sum 題目連結 官網題目說明: 解法: 從給定的一組值內找出第一組兩數相加剛好等於給定的目標值,暴力解很簡單(只會這樣= =),兩個迴圈,只要找到相加的值就跳出. /// <summa ...

  2. Leetcode 笔记 113 - Path Sum II

    题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...

  3. Leetcode 笔记 112 - Path Sum

    题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...

  4. POJ 2739. Sum of Consecutive Prime Numbers

    Sum of Consecutive Prime Numbers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20050 ...

  5. BZOJ 3944 Sum

    题目链接:Sum 嗯--不要在意--我发这篇博客只是为了保存一下杜教筛的板子的-- 你说你不会杜教筛?有一篇博客写的很好,看完应该就会了-- 这道题就是杜教筛板子题,也没什么好讲的-- 下面贴代码(不 ...

  6. [LeetCode] Path Sum III 二叉树的路径和之三

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

  7. [LeetCode] Partition Equal Subset Sum 相同子集和分割

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  8. [LeetCode] Split Array Largest Sum 分割数组的最大值

    Given an array which consists of non-negative integers and an integer m, you can split the array int ...

  9. [LeetCode] Sum of Left Leaves 左子叶之和

    Find the sum of all left leaves in a given binary tree. Example: 3 / \ 9 20 / \ 15 7 There are two l ...

  10. [LeetCode] Combination Sum IV 组合之和之四

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

随机推荐

  1. Python 网络爬虫 007 (编程) 通过网站地图爬取目标站点的所有网页

    通过网站地图爬取目标站点的所有网页 使用的系统:Windows 10 64位 Python 语言版本:Python 2.7.10 V 使用的编程 Python 的集成开发环境:PyCharm 2016 ...

  2. C语言-郝斌笔记-007是否为素数

    是否为素数 # include <stdio.h> bool IsPrime(int val) { int i; ; i<val; ++i) { ) break; } if (i = ...

  3. 打印sql语句

    root->trace hibernate->trace ,然后,改配置 全文搜索:show_sql,将所有的show_sql改为true. 这样,就会显示sql语句了.

  4. Oracle数据库之多表查询一

    上一篇给大家介绍了数据的单表查询,相信大家对于单表的查询应该都有了一些了解.单表查询在数据库中的使用会有一些,但并不是很多,但是作为初学者,我们需要学习单表查询的思路.今天呢,我们为大家介绍一下数据库 ...

  5. 如何使用ArcPy

    ArcPy可以很方便的通过脚本调用ArcGIS的各种函数和功能.在此简单介绍一下.方法包括两种,第一种是直接使用ArcGIS中的命令行,输入一句,执行一句:第二种是创建一个Python脚本,直接执行其 ...

  6. c/c++ 字符编码与标识符

    说明: 对于比较现代的语言来讲字符编码不是个大问题:java就可以使用中文作为变量名称,但对于C/C++来讲却不是这样,由于历史原因,标准和编译器厂商的实现总在不停的变化,相关编码信息到底是如何处理的 ...

  7. Visual Studio 2017中如何创建安装打包项目

    从Visual Studio 2012开始,微软就不在环境中自动集成安装打包项目了,如果还想使用,需要手动下载安装,这里以在Visual Studio 2017上安装打包项目为例进行介绍,步骤如下: ...

  8. C# 快速排序--二分查找法--拉格朗日插值法

    1.快速排序  参考自: https://www.cnblogs.com/yundan/p/4022056.html namespace 快速排序算法 { class Program { static ...

  9. html中img标签的url如何拼接变量

    <img id="pic" /> <script type="text/javascript"> var url = "xxx ...

  10. Mybatis环境搭建中的案例分析 及 如果自己编写DAO接口的实现类

    Mybatis环境搭建中的案例分析public static void main (String[] args) throws Exception { //读配置文件 //第一个: 使用类加载器,只能 ...