Two Sums问题

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.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

题解:

这道题是比较经典处理数组的,有以下两个思路。

思路1

 利用HashMap,把target-numbers[i]的值放入hashmap中,value存index。遍历数组时,检查hashmap中是否已经存能和自己加一起等于target的值存在,存在的话把index取出,连同自己的index也出去,加1(index要求从1开始)后存入结果数组中返回。如果不存在的话,把自己的值和index存入hashmap中继续遍历。由于只是一遍遍历数组,时间复杂度为O(n)。

代码如下:

 1     public int[] twoSum(int[] numbers, int target) {
 2         int [] res = new int[2];
 3         if(numbers==null||numbers.length<2)
 4             return res;
 5         HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
 6         for(int i = 0; i < numbers.length; i++){
 7             if(!map.containsKey(target-numbers[i])){
 8                 map.put(numbers[i],i);
 9             }else{
10                 res[0]= map.get(target-numbers[i])+1;
11                 res[1]= i+1;
12                 break;
13             }
14         }
15         return res;
16     }

HashMap介绍:

HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实现类。虽然 HashMap 和 HashSet 实现的接口规范不同,但它们底层的 Hash 存储机制完全一样,甚至 HashSet 本身就采用 HashMap 来实现的。

实际上,HashSet 和 HashMap 之间有很多相似之处,对于 HashSet 而言,系统采用 Hash 算法决定集合元素的存储位置,这样可以保证能快速存、取集合元素;对于 HashMap 而言,系统 key-value 当成一个整体进行处理,系统总是根据 Hash 算法来计算 key-value 的存储位置,这样可以保证能快速存、取 Map 的 key-value 对。

在介绍集合存储之前需要指出一点:虽然集合号称存储的是 Java 对象,但实际上并不会真正将 Java 对象放入 Set 集合中,只是在 Set 集合中保留这些对象的引用而言。也就是说:Java 集合实际上是多个引用变量所组成的集合,这些引用变量指向实际的 Java 对象。
就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java 对象放入数组中,只是把对象的引用放入数组中,每个数组元素都是一个引用变量。

思路2

又碰到敏感的关键字array和target,自然而然想到二分查找法。但是这道题不能像传统二分查找法那样舍弃一半在另外一半查找,需要一点点挪low和high指针,所以时间复杂度为O(n)。

首先先将整个list拷贝并排序,使用Arrays.Sort()函数,时间复杂度O(nlogn)

然后利用二分查找法,判断target和numbers[low]+numbers[high]。

target == numbers[low]+numbers[high], 记录copy[low]和copy[high];

target > numbers[low]+numbers[high],说明最大的和最小的加一起还小于target,所以小值要取大一点,即low++;

target > numbers[low]+numbers[high], 说明最大的和最小的加一起大于target,那么大值需要往下取一点,即high--。

再把找到的两个合格值在原list中找到对应的index,返回即可。

总共的时间复杂度为O(n+nlogn+n+n) = O(nlogn)。

代码如下:

  1  public int[] twoSum(int[] numbers, int target) {
 2         int [] res = new int[2];
 3         if(numbers==null||numbers.length<2)
 4             return res;
 5         
 6         //copy original list and sort
 7         int[] copylist = new int[numbers.length];  
 8         System.arraycopy(numbers, 0, copylist, 0, numbers.length);  
 9         Arrays.sort(copylist);    
10         
11         int low = 0;
12         int high = copylist.length-1;
13         
14         while(low<high){
15             if(copylist[low]+copylist[high]<target)
16                 low++;
17             else if(copylist[low]+copylist[high]>target)
18                 high--;
19             else{
20                 res[0]=copylist[low];
21                 res[1]=copylist[high];
22                 break;
23             }
24         }
25         
26         //find index from original list
27         int index1 = -1, index2 = -1;  
28         for(int i = 0; i < numbers.length; i++){  
29             if(numbers[i] == res[0]&&index1==-1)
30                 index1 = i+1;
31             else if(numbers[i] == res[1]&&index2==-1)
32                 index2 = i+1;
33        } 
34         res[0] = index1;
35         res[1] = index2;
36         Arrays.sort(res);
37         return res;
38     }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值