题目描述:简单难度
给定一个数组和一个目标和,从数组中找两个数字相加等于目标和,输出这两个数字的下标。
解法一 双层循环
简单粗暴些,两重循环,遍历所有情况看相加是否等于目标和,如果符合直接输出。
Java
public class Two_Sum {
public static int[] twosum(int[] nums,int target) {
int[] ans=new int[2];
for(int i=0;i<nums.length;i++) {
for(int j=i+1;j<nums.length;j++) {
if(nums[i]+nums[j]==target) {
ans[0]=i;
ans[1]=j;
return ans;
}
}
}
return ans;
}
public static void main(String args[]) {
int[] nums= {2,7,11,15};
int target=9;
int[] ans=twosum(nums,target);
for(int i:ans) {
System.out.println(i);
}
}
}
时间复杂度:两层 for 循环,O(n²)
空间复杂度:O(1)
Python
class Solution(object):
def twoSum(self, nums, target):
ans=[]
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if(nums[i]+nums[j]==target):
ans.append(i)
ans.append(j)
return ans
return ans片
解法二 双重哈希表
在上边的解法中看下第二个 for 循环步骤。
for(int j=(i+1);j<nums.length;j++){
if(nums[i]+nums[j]==target){
我们换个理解方式:
for(int j=(i+1);j<nums.length;j++){
sub=target-nums[i]
if(nums[j]==sub){
第二层 for 循环无非是遍历所有的元素,看哪个元素等于 sub
,时间复杂度为 O(n)。
有没有一种方法,不用遍历就可以找到元素里有没有等于 sub
的?
就是哈希表!
我们可以把数组的每个元素保存为 hash
的 key
,下标保存为 hash
的 value
。
这样只需判断 sub
在不在 hash
的 key
里就可以了,而此时的时间复杂度仅为 O(1)!
为什么哈希表查询此时的时间复杂度是 O(1),那么到底是什么保证了这一特性呢,这个就要从hashmap的底层存储结构说起,下来看一张图:
上面就是hashmap的底层存储示意图,要想查看一个键值对应的值,首先根据该键值的hash值找到该键的hash桶位置,即是tab[2]还是tab[1]等,计算某个键对应的哈希桶位置很简单,就是int pos = (n - 1) & hash
,也就是hash%n
,因为位运算效率高所以在hashmap实现时使用的是位运算这种方式,需要注意的是哈希桶的数量必须是2^n,所以hashmap一旦扩容必定是哈希桶数量翻番。
通过上面的描述,我们可以知道,根据键值找到哈希桶的位置时间复杂度为O(1),使用的就是数组的高效查询。
需要注意的地方是,还需判断找到的元素不是当前元素,因为题目里讲一个元素只能用一次。
在Java中,HashMap
就是字典,put
方法加入新数据,containKey
查询key
值是否存在,get
方法查找value
值。
Java
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < nums.length; i++){
map.put(nums[i], i);
}
for(int i = 0;i <nums.length; i++){
int sub = target - nums[i];
if(map.containsKey(sub) && map.get(sub) != i){
return new int[]{i, map.get(sub)};
}
}
return null;
}
}
时间复杂度:比解法一少了一个 for 循环,降为 O(n)
空间复杂度:所谓的空间换时间,这里就能体现出来, 开辟了一个 hash table ,空间复杂度变为 O(n)
Python
其中,在python中,字典添加数据的方法为为update
,查找key
值的方式为 for key in dict
,查找value
值的方式为dict.get(key)
class Solution(object):
def twoSum(self, nums, target):
dic = {}
ans = []
for i in range(len(nums)):
dic.update({nums[i]:i})
for i in range(len(nums)):
sub = target - nums[i]
if(sub in dic and dic.get(sub) != i):
ans.append(i)
ans.append(dic.get(sub))
return ans
总结
python字典(dict)添加数据格式
dict.update({key,value})
python列表(List)添加数据格式
list.append(key)
python列表(List)查找数据格式
list.get(key)#value
java字典(HashMap)添加数据格式
map.put(key,value)
java字典(HashMap)判断元素是否存在
map.containsKey(key)
java字典(HashMap)查找数据格式
map.get(key) //value
这道题目巧妙的使用了哈希表进行处理