leetcode简单难度--第一题--两数之和

题目:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

实例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

/**
	 * 暴力穷举法,有2点缺陷
	 * 1、使用了flag来标识是否结束,太麻烦了,不如直接return,以及使用了 i1  i2两个变量,没必要,直接new一个int[]更简洁
	 * 2、当没有结果的时候return null 不是很合理,毕竟题目说的是一定会有结果,因此改为抛出异常更合理一些
	 * @param nums
	 * @param target
	 * @return
	 */
	public static int[] numAdd(int[] nums,int target){
		boolean flag = false;
		int i1 = 0;
		int i2 = 0;
		for(int i = 0;i < nums.length - 1;i++){
			for(int j = i+1;j < nums.length;j++){
				if(nums[i] + nums[j] == target){
					System.out.println("找到结果了");
					i1 = i;
					i2 = j;
					flag = true;
					break;
				}
			}
			if(flag){
				break;
			}
		}
		
		if(flag){
			int[] numss = {i1,i2};
			return numss;	
		}else{
			return null;
		}
		
	}
/**
	 * 暴力穷举法的改良版,更加简洁高效了
	 * @param nums
	 * @param target
	 * @return
	 */
	public static int[] numAdd2(int[] nums,int target){
		
		for(int i = 0;i < nums.length - 1;i++){
			for(int j = i+1;j < nums.length;j++){
				if(nums[i] + nums[j] == target){
					System.out.println("找到结果了");
					return new int[]{i,j};
				}
			}
		}
		throw new IllegalArgumentException("No two sum solution");
	}
/**
	 * 以上方法最主要的缺陷还是双重for循环的效率很低,循环次数太多了,因此想办法优化
	 * 要看到这个问题的本质,其实就是一点:找到一个数组中我们所需要的特定值的下标
	 * 也就是说,我们需要找到一个特定值,同时找到它的索引,值与索引的关系让我们想到了 Hash算法
	 * 所以我们用HashMap来存数据,key为数组的值,value为数组索引,然后利用这个Map来进行操作
	 * 注意这里的key跟value不能搞反了,我们已知的是我们需要的目标值,需要找到的是目标值(如果有)的下标
	 * 因此key value就很明显了,弄反了的话还是一样需要循环这个map中的value Set集合,计算的复杂度大大提高,
	 * 可能会想到Map方法的一个API,是containsValue,利用这个表面上看不需要多一次循环,但是,想一想哈希算法的实现原理,就会知道
	 * 其实底层还是在循环的!所以不行
	 * 
	 * 虽然还是有2个for循环,但是呢,不是嵌套的了,效率自然也会大大提高
	 * 
	 * 可能会疑惑,要是数组中有元素值一样的元素的话,那么Map里面不就覆盖了吗?但是根据题意,我们只需要得出一个结果,重复的话并不影响我们结果的准确性!
	 *  
	 * @param nums
	 * @param target
	 * @return
	 */
	public static int[] numAdd3(int[] nums,int target){
		
		Map<Integer, Integer> map = new HashMap<Integer,Integer>();
		
		for(int i = 0;i < nums.length;i++){
			map.put(nums[i], i);
		}
		for(int j = 0;j < nums.length - 1;j++){
			// 唯一需要注意的点是:不能用数组中同一个元素相加等于目标值
			/*
			Integer value = map.get(target - nums[j]);
			if(value != null && value != j){
				return new int[]{j,map.get(target - nums[j])};
			}
			*/
			// 上面的写法也可以,但是不够简洁,利用已有API简化代码,如下
			int targetValue = target - nums[j];
			if(map.containsKey(targetValue) && map.get(targetValue) != j){
				return new int[]{j,map.get(targetValue)};
			}
		}
		throw new IllegalArgumentException("No two sum solution");
	}
/**
	 * 该方法是上面利用哈希表(HashMap)的进化版,我们上面是先 循环  数组中的数据存到HashMap中,再用数组、HashMap进行  循环  计算
	 * 一共要2次循环,我们考虑能否只做一次循环,也就是在数据存到HashMap中的时候就直接进行比较,
	 * 分析:在把数组的元素放到Map中的时候,就看看Map中的元素与即将要丢进去的元素是不是满足要求 ,因为我们会遍历完数组的,所以这样也不会遗漏数据
	 * 并且,还有一个好处,就是不会有重复的元素出现了,因为都是即将放入的元素与Map中已有的元素进行比较的
	 * 
	 * ps:唯一需要注意的是,Map中的value以及数组的下标在return的数组中哪个在前哪个在后的问题,我们按照习惯把小的放前面
	 * 
	 * @param nums
	 * @param target
	 * @return
	 */
	public static int[] numAdd4(int[] nums,int target){
		
		Map<Integer, Integer> map = new HashMap<Integer,Integer>();
		for(int i = 0;i < nums.length - 1;i++){
			
			int targetValue = target - nums[i];
			if(map.containsKey(targetValue)){
				return new int[]{map.get(targetValue),i};
			}
			map.put(nums[i], i);
		}
		throw new IllegalArgumentException("No two sum solution");
	}
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值