Leetcode 题解 - 哈希表(1):数组中两个数的和为给定值

哈希表使用 O(N) 空间复杂度存储数据,并且以 O(1) 时间复杂度求解问题。

  • Java 中的 HashSet 用于存储一个集合,可以查找元素是否在集合中。如果元素有穷,并且范围不大,那么可以用一个布尔数组来存储一个元素是否存在。例如对于只有小写字符的元素,就可以用一个长度为 26 的布尔数组来存储一个字符集合,使得空间复杂度降低为 O(1)。

  • Java 中的 HashMap 主要用于映射关系,从而把两个元素联系起来。HashMap 也可以用来对元素进行计数统计,此时键为元素,值为计数。和 HashSet 类似,如果元素有穷并且范围不大,可以用整型数组来进行统计。在对一个内容进行压缩或者其它转换时,利用 HashMap 可以把原始内容和转换后的内容联系起来。例如在一个简化 url 的系统中 Leetcdoe : 535. Encode and Decode TinyURL (Medium),利用 HashMap 就可以存储精简后的 url 到原始 url 的映射,使得不仅可以显示简化的 url,也可以根据简化的 url 得到原始 url 从而定位到正确的资源。

[LeetCode] Two Sum 两数之和

建立一个hashmap存储nums[i] 和 i 的键值对 ,

第二次for循环去找 target - nums[i] 是否存在

存在的话直接 直接去的两个值下标

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.

Example:

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

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

 

啦啦啦,欢迎开启LeetCode刷题的旅程,这将是一段漫长而又艰辛的旅程,这是一条攀登珠穆朗玛的皑皑雪山路,这是通向One Piece宝藏的伟大航路,这是成为火影的无比残酷的修罗场,这是打破吊丝与高富帅之间界限的崩玉。但请不要害怕,在老船长Grandyang博主的带领下,必将一路披荆斩棘,将各位带到成功的彼岸,不过一定要牢记的是,不要下船,不要中途放弃,要坚持,要自我修炼,不断成长!那么,起航吧~这道Two Sum的题目作为LeetCode的开篇之题,乃是经典中的经典,正所谓‘平生不识TwoSum,刷尽LeetCode也枉然’,就像英语单词书的第一个单词总是Abandon一样,很多没有毅力坚持的人就只能记住这一个单词,所以通常情况下单词书就前几页有翻动的痕迹,后面都是崭新如初,道理不需多讲,鸡汤不必多灌,明白的人自然明白。

这道题给了我们一个数组,还有一个目标数target,让我们找到两个数字,使其和为target,乍一看就感觉可以用暴力搜索,但是猜到OJ肯定不会允许用暴力搜索这么简单的方法,于是去试了一下,果然是Time Limit Exceeded,这个算法的时间复杂度是O(n^2)。那么只能想个O(n)的算法来实现,由于暴力搜索的方法是遍历所有的两个数字的组合,然后算其和,这样虽然节省了空间,但是时间复杂度高。一般来说,我们为了提高时间的复杂度,需要用空间来换,这算是一个trade off吧,我们只想用线性的时间复杂度来解决问题,那么就是说只能遍历一个数字,那么另一个数字呢,我们可以事先将其存储起来,使用一个HashMap,来建立数字和其坐标位置之间的映射,我们都知道HashMap是常数级的查找效率,这样,我们在遍历数组的时候,用target减去遍历到的数字,就是另一个需要的数字了,直接在HashMap中查找其是否存在即可,注意要判断查找到的数字不是第一个数字,比如target是4,遍历到了一个2,那么另外一个2不能是之前那个2,整个实现步骤为:先遍历一遍数组,建立HashMap映射,然后再遍历一遍,开始查找,找到则记录index。代码如下:

 

class Solution {
    public int[] twoSum(int[] nums, int target) {        
        HashMap<Integer, Integer> hm = new HashMap<>();
        int n = nums.length;
        int[] res = new int[2];
        for(int i=0; i<n; i++){
            hm.put(nums[i], i);
        }
        //再次遍历 以差值进行寻找 这样可以一次找出i值和与i位置相加等于target的值
        for(int i=0; i<n; i++){
            int t = target - nums[i];
            if(hm.containsKey(t) &&  hm.get(t) != i){
                res[0] = i;
                res[1] = hm.get(t);
                break;
            }
        }
        return res;
    }
}

 

暴力解法:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        
        int n = nums.length;
        int[] res = new int[2];
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                if(nums[i] + nums[j] == target){
                    res[0] = i;
                    res[1] = j;
                    return res;
                }
            }            
        }
        return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值