关于leetcode:LeetCode专题1-两数之和-探究HashMap的原理及源码

39次阅读

共计 1787 个字符,预计需要花费 5 分钟才能阅读完成。

0 前言

本专题将基于 LeetCode 的题目来剖析最佳解决方案背地的一些数据结构与算法原理。
本文将基于题目 #1 两数之和来剖析 JAVA 中 HashMap 原理及高性能起因。

1 题目形容

两数之和

给定一个整数数组 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]

提醒:

  • 2 <= nums.length <= 103
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个无效答案

2 最佳计划及疑难

最容易想到的解决方案是暴力枚举,循环嵌套,空间复杂度只有O(1),但工夫复杂度是O(N ^2)。更优的计划是基于哈希表(如 JAVA 中 HashMap)来放慢数据查问的效率,用空间来换工夫,使工夫和空间的复杂度均为O(N)

具体形容及代码可见:https://leetcode-cn.com/probl…

此处的疑难是,为什么用哈希表就能够显著晋升查问效率呢?

3 哈希表原理剖析

1、为什么会有哈希表这种构造、它由什么组成?

咱们已知的构造有数组和链表,两者各有优缺点:

  • 数组 :数组存储构造是间断的,空间复杂度大,但查问的工夫复杂度小。其寻址(通过下标搜寻) 效率高,个别的插入和删除效率低。即,查问快,增删慢
  • 链表 :链表存储构造是离散的,空间复杂度小。其寻址(通过下标搜寻) 效率低,个别的插入和删除效率高。即,查问慢,增删快

哈希表是基于数组和链表构建的,目标是为了充分发挥这两个构造的劣势。

对于一个哈希表,其蕴含四个局部的内容:

  • key:即键值
  • value:即数值
  • hash:key 对应的 hash 值,基于 hash 进行某种操作后失去的是表的 index
  • next:当 index 抵触时,寄存抵触的数据,链表构造

2、为什么哈希表的查问效率会高于数组呢?

因为哈希表的构造也有点相似于字典。字典通过 key 能够疾速查问到 value,哈希表一样能够通过 key 疾速查问到 value,但其中间进行了散列变换(即 hash 计算),通过 hash 值来确定 value 所在的 index,从而实现数据的获取。

一个确定的 key 能够计算失去惟一的 hash 值,而 index 是 hash 通过某种操作失去的,难以不免 hash 值的抵触,为了解决这个抵触才引入了链表,来高效的存储 hash 值雷同的值。

3、 hashMap.containsKey(value)的工夫复杂度是多少?

HashMap 在不同版本的 JDK 之间有着如下的区别:

  • JDK 1.8 以前 HashMap 由数组和链表形成。
  • JDK 1.8 之后 HashMap 由数组、链表和红黑树形成。

红黑树的特点是查问快,增删慢。
红黑树 作为一种二叉查找树,但它在二叉查找树的根底上减少了着色和相干的性质使得红黑树绝对均衡,从而保障了红黑树的查找、插入、删除的工夫复杂度最坏为 O(log n)。因为链表的查问工夫复杂度为 O(n),所以当链表很长时转换成红黑树将很好的提高效率!

红黑树的引入是为了解决,当抵触产生时,链表太长而带来的查问性能降落的问题。在 JDK 1.8 中规定,当链表长度大于 8 后,链表转为红黑树结构。转换之前最坏的工夫复杂度为O(N),转换之后的最坏工夫复杂度为O(logn)

HashMap 的原理解说举荐视频(p6-p9):https://www.bilibili.com/vide…
红黑树的原理举荐:https://www.cnblogs.com/yyxt/…

综上:
JDK 1.8 以前,hashMap.containsKey(value)最好状况便是 O(1),最坏状况是 O(n)
JDK 1.8 当前,hashMap.containsKey(value)最好状况便是 O(1),最坏状况是 O(lgn)

4 HashMap 源码剖析

这篇文章解说的很清晰,不再赘述。
https://blog.csdn.net/qingtia…

如果该文章看不懂,能够先看看上文说到的视频。

正文完
 0