Two Sum -- Easy

版权声明:本文为博主原创文章,未经博主允许不得转载。

一、问题描述

  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, and you may not use the same element twice.

  意思是给定一个数组和目标数,以数组中任意两数之和为目标数的下标作为新数组元素,返回一个数组。

二、生词

  indices    n /'ɪndɪsiːz/ 索引(index的复数)

三、样例及说明

  

四、解题思路及代码

  我首先想到的方法就是暴力破解。。。时间复杂度为O(n^2)

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3         for(int i = 0; i < nums.length-1; i ++) {
 4             for(int j = i+1; j < nums.length; j++) {
 5                 if(nums[i] + nums[j] == target) 
 6                     return new int[] {i,j} ;
 7             }
 8         }
 9         return null;
10     }
11 }

  但是在跟答案的暴力破解相比的话,自己的代码有一个地方没有处理好,就是当没有找到相应的元素时,我返回的是一个null,显然这是不对的(虽然运行的时候没有错误)。

所以应该抛一个异常告诉调用者。

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3         for(int i = 0; i < nums.length-1; i ++) {
 4             for(int j = i+1; j < nums.length; j++) {
 5                 if(nums[i] + nums[j] == target) 
 6                     return new int[] {i,j} ;
 7             }
 8         }
 9         throw new IllegalArgumentException("No two sum solution");
10     }
11 }

  暴力破解法在运行时的复杂性提高的时候性能是非常劣势的,所以需要用一种更为有效的方法去检测目标数是否合法——哈希表!

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3        Map<Integer,Integer> map = new HashMap<Integer,Integer>() ;
 4         for(int i=0; i < nums.length; i++) {
 5             map.put(nums[i],i);
 6         }
 7         for(int i=0; i < nums.length; i++) {
 8             int complement = target - nums[i];
 9             if(map.containsKey(complement) && map.get(complement) != i) {
10                 return new int[] {i,map.get(complement)} ;
11             }
12         }
13         throw new IllegalArgumentException("No two sum solution") ;
14     }
15 }

  此时时间复杂度就降为了O(n)!上述代码第一个for循环先把数组中的key和value存放进容器中,由第二个for循环去判断目标数是否合法。但其实可以进一步优化代码-仅用一个for循环即可。

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3        Map<Integer,Integer> map = new HashMap<Integer,Integer>() ;
 4         for(int i=0; i < nums.length; i++) {
 5             int complement = target - nums[i] ;
 6             if(map.containsKey(complement)&&map.get(complement) != i) return new int[] {map.get(complement),i} ;
 7             map.put(nums[i],i);
 8         }
 9         throw new IllegalArgumentException("No two sum solution") ;
10     }
11 }

  和用暴力破解相比用哈希表的运行时间提了将近七倍!

五、知识点补缺补漏

  Map接口:public interface Map<K,V>  将键映射到值的对象。映射不能包含重复的键;每个键最多只能映射到一个值。

  在Map接口下,有两个常用子类:HashMap、HashTable

  常用方法:

  1. public V put(K key,V value) :向集合中保存数据
  2. public V get(Object key) :根据key查找对应的value数据
  3. public boolean containsKey(Object key) :如果该映射保护键值key就返回true,否则返回false

 

posted @ 2019-02-24 21:31  Aion_14  阅读(147)  评论(0)    收藏  举报