算法学习-查找数组中两个值的和为目标值

算法学习-查找数组中两个值的和为目标值

                                     告别浮躁,回归初心

 

从简单入手

 

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。假设只存在一个有效答案

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

 

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

 

示例 3:

输入:nums = [3,3], target = 6

输出:[0,1]

 

开发常用

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

 

 类似于游标的做法

 

 

 这是常用的做法,在开发中也差不多这种用的最普遍,老师教学中也常用此作为教学

缺点,时间复杂度高,运行时间长

 

改进算法

利用hashmap的hashkey作为目标数去查找 

public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            if(map.containsKey(nums[i])){
          //如果保存的hashmap中恰好存在 target-X的key则返回
return new int[]{map.get(nums[i]), i}; } map.put(target - nums[i], i); } return null; }

利用Hashmap,使用hash key作为查询,对大数据可以做到快速定位和查找。只需循环查找一次,查到下一个数据,用目标数减去当前数值后的key如果存在,则返回。

 

衍生知识

   Hashmap快速存储特点原理

数组和链表各自特点

数组:

  存储区间是连续,且占用内存严重,空间复杂也很大,时间复杂为O(1),是随机读取效率很高,原因数组是连续(随机访问性强,查找速度快)

  插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中要往后移的,且大小固定不易动态扩展。

链表

  区间离散,占用内存宽松,空间复杂度小,时间复杂度O(N),插入删除速度快,内存利用率高,没有大小固定,扩展灵活

  不能随机查找,每次都是从第一个开始遍历(查询效率低)。

能否集两家所长,实现查询效率高和插入删除效率也高的数据结构,答案是肯定的

  哈希表

 map.put(k,v)实现原理

  1. 首先将k,v封装到Node对象当中(节点)。
  2. 底层会调用K的hashCode()方法得出hash值。
  3. 通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

map.get(k)实现原理

  1. 先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
  2. 通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。重点理解如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着参数K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

总结下就是如图

 

 

 

     使用hash算法算出hash值,然后将hash值转换成数组的下标。若数组那里不存在值,则存入该值;若已经存在,则延长为链表跟在后面。插入和查询以此类推

     理论上该算法时间复杂度最高为O(1),随着数据量增大,冲突过多一定会大于O(1)。

  附:  JDK8之后,当链表元素为6个和8个分别作为红黑树转链表,链表转红黑树的阈值。

      

 

 

 

参考资料

来复习一波,HashMap底层实现原理解析

HashMap底层实现和原理

posted @ 2021-03-13 21:32  verification  阅读(794)  评论(0)    收藏  举报