力扣刷题-两数之和
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
虽然是简单题目,但java有一段时间没写很多基础概念掌握不牢,最后还是搜索了多方答案才看懂怎么实现,下面给出三种方法来解决该问题:
一、暴力递归法
开始尝试使用的第一种方法就是这个,因为语法忘记导致没有实现。
class Solution {
public static int[] twoSum(int[] nums, int targer){
//循环嵌套,对每一个元素进行遍历搜索,Public访问修饰符,static关键字,int[]返回类型,twoSum方法名,
//(int[] nums , int targer)为输入类型 ,分别是整形数组和整形
for (int i=0;i<nums.length;i++){//以上述nums=[2,7,11,15]为例,首先遍历数组里的0,1,2,3
for (int j=i+1; j<nums.length;j++){//i为3不进入循环
if(nums[j]+nums[i]==targer){
return new int[]{i,j};
}
}
}
throw new IllegalArgumentException("No to sum solution");
}
}
该方法使用了两遍遍历,第一个循环花费时间为n次,第二个循环(n-1)次,最后花费的时间复杂度是T(n)=O(n^2),空间复杂度是O(n)=1。
二、哈希表(增大使用空间,减少时间开销)
首先复习下哈希映射:
哈希表基本表示为(key,value),一个key值对应一个value。
基础概念(转自菜鸟教程RUNOOB.com)
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 是无序的,即不会记录插入的顺序。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
常用方法如下:
HashMap类位于java.util包中,使用前需进行引入,语法格式如下:
import java.util.HashMap;//引入HashMap类
以下实例可创建一个HashMap对象Sites,整形(int)的key和字符串(str)类的value。
HashMap<Intrger,String> Sites = new HashMap<Integer,String>();
2.1 两遍哈希表
import java.util.HashMap;
class Solution {
public static int[] twoSum(int[] nums,int target){
//java不能直接提取索引,采用哈希表的方式来让数组和索引对应
//1、创建一个HashMap,键值的泛型为Integer
Map<Integer,Integer> map = new HashMap<>();
//2、第一次循环把数组放入哈希表
for(int i =0;i<nums.length;i++){
//元素key,索引value
map.put(nums[i],i);
}
//3、第二次迭代判断是否符合条件元素在哈希表中,取出两个索引
for(int i=0;i<nums.length;i++){
int value = target - nums[i];//得到符合条件的值
//再判断是否在哈希表中,且不能与自身相等
if(map.containsKey(value)&&map.get(value)!=i){
return new int[]{i,map.get(value)};
}
}
throw new IllegalArgumentException("没有满足条件的数");
}
}
该方法因为使用了两次循环,而且因为哈希表的存储空间与创立的数组大小有关系,没有循环嵌套因此T(n)=O(n)=n^2。
2.2一遍哈希表
import java.util.HashMap;
class Solution {
public static int[] twoSum(int[] nums,int target){
//创建一个哈希表,key-value泛型为Integer
Map<Integer,Integer> map = new HashMap<>();
//仅做一次迭代,迭代的时候判断里面是否含有该元素,如果有,则返回下标索引,没有则进行放入哈希表。
for (int i=0;i<nums.length; i++){
int value = target - nums[i];
//判断哈希表中是否含有数据,有则返回i的数值和哈希表中索引
if(map.containsKey(value)){
return new int[]{map.get(value), i};
}
//若没有则把数组中的数放入哈希表
map.put(nums[i],i);
}
throw new IllegalArgumentException("没有满足条件的数");
}
}
仅做一次哈希表时间复杂度和空间复杂度都为T(n)=O(n)=n,总体来看是最优解。
很久没接触有的忘记了,很多地方是借鉴了别人的想法,如果有错误的地方还请指出。