继续算法系列。今天再看一道leetcode(www.leetcode.com)的题目。
问题描述
原文
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.You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
大意:给定一个整型数组,在其中寻找两个数字,使得这两个数字的和等于特定的值。**要求返回这两个数字的索引,其中索引index1应该小于index2,索引从1开始。假设给定的值在数组中仅有两个数字之和与之相等。
例如:输入:数组numbers={2,7,11,15},目标值target=9
输出:index1=1,index2=2
思路分析
看到要求,第一时间想到的肯定是双层循环的写法,通过遍历数组,不断求和与给定target值比较,最终肯定可以找到这两个数。但是需要注意的是,这种方法的时间复杂度是O(n²),显然是所有方法中效率最低的一种。照例,我们也先给出这种方法的代码,然后再来寻找更加高效的写法。
public int[] twoSum(int[] nums, int target) {
int len = nums.length;
int index1 = 0, index2 = 0;
if (len <= 1)
return null;
for (int i = 0; i < len; i++)
for (int j = i + 1; j < len; j++)
if (nums[i] + nums[j] == target) {
index1 = i + 1;
index2 = j + 1;
break;
}
return new int[] { index1, index2 };
}
方法改进
以上代码虽然容易想到,但是效率较低,制约效率提升的关键在于循环本身,算法把大量的时间开销用于查找,因此我们可以预先构造hash表存储值与索引的对应关系,从而减少查找的时间,提升程序性能。
下面给出改进后的代码。
public class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map=new HashMap<Integer,Integer>();
int[]result=new int[2];
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
result[0]=map.get(target-nums[i])+1;
result[1]=i+1;
return result;
}
}
return null;
}
}
效率分析:以上代码将程序时间复杂度降到了O(n),但是却增加了空间消耗,空间复杂度为O(n),这两种方式各有优缺点,实际使用中要根据要求灵活运用。