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. GUI编程01

    1 tkinter TkInter是标准的Python GUI库.的Python与Tkinter的结合提供了一个快速和容易的方法来创建GUI应用程序. Tkinter的提供了一个强大的面向对象的接口T ...

  2. SQL server2008无法收缩日志

    SQL server2008无法收缩日志,错误信息为: 1:由于最小日志空间要求,无法收缩日志文件 2:无法收缩日志文件 2 (XXX_log),因为该文件结尾的逻辑日志文件正在使用 描述: 用的是网 ...

  3. nexus admin 从文件角度进行密码重置

    \sonatype-work\nexus\conf\security.xml 文件中保存账号密码信息. 打开 vi nexus-2.10.0-02-bundle\sonatype-work\nexus ...

  4. The Apache Tomcat installation at this directory is version 8.5.24 Tomcat 8.0 installation is expect

    在一台新电脑上搭建Java开发环境,JDK 是1.8,Tomcat下载了Tomcat 8.5.24,已经配置好了Java和Tomcat的环境变量,开发工具是Eclipse MARS,准备在Eclips ...

  5. (转)typedef和#define的用法与区别

    typedef和#define的用法与区别 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,实例像: ...

  6. PCL—点云分割(超体聚类) 低层次点云处理

    博客转载自:http://www.cnblogs.com/ironstark/p/5013968.html 1.超体聚类——一种来自图像的分割方法 超体(supervoxel)是一种集合,集合的元素是 ...

  7. Java-马士兵设计模式学习笔记-工厂模式-简单工厂

    一.概述 1.目标:要控制任意类型交通工具的生产模式 2.目标有两层意思(1)任意类型 (2)生产模式,所以对应的,要这两个层面上抽象(Movable,VehicleFactory),利用接口,实现多 ...

  8. R: 字符串处理包:stringr

    本文摘自:  http://blog.fens.me/r-stringr/ 1. stringr介绍 stringr包被定义为一致的.简单易用的字符串工具集.所有的函数和参数定义都具有一致性,比如,用 ...

  9. FPM包定制完成 (等待实现 里程碑 1 和 2) 2018年4月13日 2:18:32

    前期环境准备: 关闭SELINUX  :   setenforce 0 关闭SELINUX  :   sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' / ...

  10. win10下安装配置mysql-8.0.13--实战可用

    1.下载mysql-8.0.13安装包 1 https://dev.mysql.com/downloads/mysql/ 选择zip安装包下载就好. 2.解压到你要安装的目录 3.创建my.ini配置 ...