引入题目:两数相加

* 给定一个整数数组 nums 和一个目标值 target
* 请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
* 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 来源:LeetCode

第一种方法:暴力法

通过遍历数组的其余部分来寻找它所对应的目标元素

/**
* 暴力法
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
*
* @param nums
* @param target
* @return
*/
public static int[] twoSum1(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
//因为 nums[0] + nums[1] = 2 + 7 = 9
if ((nums[i] + nums[j]) == target) {
//所以返回 [0, 1]
return new int[]{i, j};
}
}
} throw new IllegalArgumentException("No two sum solution");
}

第二种方法:两遍哈希表

通过以空间换取速度的方式。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i])是否存在于表中。

/**
* 两遍哈希表
* 时间复杂度:O(n)
* 空间复杂度:O(n)
* @param nums
* @param target
* @return
*/
public static int[] twoSum2(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
//将每个元素的值和索引添加到表中
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
//检查每个元素所对应的目标元素(target - nums[i])是否存在于表中
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[]{i, map.get(complement)};
}
}
throw new IllegalArgumentException("No two sum solution");
}

方法三:一遍哈希表

在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。

/**
* 一遍哈希表
* @param nums
* @param target
* @return
*/
public static int[] twoSum3(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
//如果hashmap里存在对应的目标元素,立即存进结果集合返回
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}

通过运行,不难发现,用HashMap的方式速度要快的多。这是因为HashMap集合底层是哈希表,查询的速度特别的快。

JDK1.8之前底层数据结构采用的是:数组+单向链表

JDK1.8之后底层数据结构采用的是:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度

HashMap相关知识:

Map集合

java.util.Map<k,v>集合,是夫妻对儿集合 Map<K,V> ,定义了双列集合规范,每次存储一对儿元素

通过 可以找 对应的值 ,K代表键(Key)的类型,V代表值(Value)的类型。

Map集合的特点

  • Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
  • Map集合中的元素,key和value的数据类型可以相同,也可以不同
  • Map集合中的元素,key是唯一的,value是可以重复的
  • Map集合中的元素,key和value是一一对应

Map常用子类

HashMap集合、LinkedHashMap集合。

tips:Map接口中的集合都有两个泛型变量,在使用时要为两个泛型变量赋于数据类型。

HashMap集合

java.util.HashMap<k,v>集合 implements Map<k,v>接口

特点:

  • HashMap集合底层是哈希表:查询的速度特别的快

    ​JDK1.8之前:数组+单向链表

    ​JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度

  • hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致

  • 由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法

LinkedHashMap集合

java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合

特点:

  • LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
  • LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
  • 通过哈希表结构可以保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法

Map集合的常用方法

public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。

​ 返回值:V

​ 存储键、值对的时候,key不重复,返回值V是null

​ 存储键、值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值

public V remove(Object key): 把指定的键 所对应的键、值对元素 在Map集合中删除.

​ 返回被删除元素的值。

​ key存在,v返回被删除的值 --Integer赋值给int可以自动拆箱

​ key不存在,v返回null --Integer赋值给int会报错NullPointerException

public V get(Object key): 根据指定的键,在Map集合中获取对应的值。

​ 返回值:

​ key存在,返回对应的value值

​ key不存在,返回null

values(): 获取Map中的所有value

Map集合的第一种遍历方式:通过键找值的方式

Map集合中的方法:

Set<K> keySet(): 返回此映射中包含的键的 Set 视图。

实现步骤:

  1. 使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
  2. 遍历Set集合,获取Map集合中的每一个key
  3. 通过Map集合中的方法get(key),通过key找到value

例一种最快的:

//使用增强for遍历Set集合
for(String key : map.keySet()){
//通过Map集合中的方法get(key),通过key找到value
Integer value = map.get(key);
System.out.println(key+"="+value);
}

Map集合遍历的第二种方式:使用Entry对象遍历

Map.Entry<K,V>:在Map接口中有一个Entry接口。作用:存键、值对(结婚证)

Map集合中的方法:

Set<Map.Entry<K,V>> entrySet():获取到Map对象中所有键、值对 对象的集合(Set集合)

实现步骤:

  1. 使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
  2. 遍历Set集合,获取每一个Entry对象
  3. 使用Entry对象中的方法getKey()和getValue()获取键与值

Map集合不能直接使用迭代器或foreach进行遍历。但是转成Set之后就可以用了

HashMap存储自定义类型键值

(可以是对象,也可以是集合/数组)

Map集合保证key是唯一:对象作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一

比如:

key:Person类型

​ Person类就必须重写hashCode方法和equals方法,以保证key唯一

value:String类型

​ 可以重复

又比如:

key:String类型

​ String类重写hashCode方法和equals方法,可以保证key唯一

value:Person类型

​ value可以重复(同名同年龄的人视为同一个)

Hashtable<K,V>集合

java.util.Hashtable<K,V>集合 implements Map<K,V>接口

  • Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢

  • Hashtable集合,不能存储null值,null键

  • HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快

  • HashMap集合(之前学的所有的集合):可以存储null值,null键

  • Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了

  • Hashtable的子类Properties依然活跃在历史舞台

Properties集合是一个唯一和IO流相结合的集合

静态方法of(E... elements)

JDK9的新特性:

List接口,Set接口,Map接口: 里边增加了一个静态的方法of,可以给集合一次性添加多个元素

static List<E> of(E... elements)

使用前提:

当集合中存储的元素的个数已经确定了,不在改变时使用

注意:

  1. of方法只适用于List接口,Set接口,Map接口,不适用于接接口的实现类
  2. of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
  3. Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常

例:

Map<String,Integer> map = Map.of("a",1,"bb",2,"ccc",3);
System.out.println(map);

通过简单的两数相加体会hashmap的好处的更多相关文章

  1. 【LeetCode】两数相加

    题目描述 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和. ...

  2. LeetCode(2):Add Two Numbers 两数相加

    Medium! 题目描述: 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字.将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头 ...

  3. leetcode刷题2:两数相加add_two_numbers

    题目:两数相加 (难度:中等) 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字. 将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以 ...

  4. 两数相加(C#数据结构和算法练习)

    两数相加 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表 ...

  5. LeetCoded第2题题解--两数相加

    2.两数相加 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表 ...

  6. [CareerCup] 18.1 Add Two Numbers 两数相加

    18.1 Write a function that adds two numbers. You should not use + or any arithmetic operators. 这道题让我 ...

  7. ✡ leetcode 167. Two Sum II - Input array is sorted 求两数相加等于一个数的位置 --------- java

    Given an array of integers that is already sorted in ascending order, find two numbers such that the ...

  8. 简单的两数之和再次乱入<< Add Two Numbers >>

    请看题目描述: You are given two linked lists representing two non-negative numbers. The digits are stored ...

  9. [Swift]LeetCode2. 两数相加 | Add Two Numbers

    You are given two non-empty linked lists representing two non-negative integers. The digits are stor ...

随机推荐

  1. SEO 第一章

    SEO  第一章 第一章:SEO基础知识 第二章:搜索引擎基础 第三章:关键词分析 第四章:TDK优化 第五章:网站的URL优化 第六章:网站的内链优化 第七章:代码优化 第八章:网站的内容优化 第九 ...

  2. (转)Spring提供的CharacterEncoding和OpenSessionInView功能

    http://blog.csdn.net/yerenyuan_pku/article/details/52902282 前面我们以一种更加优雅的方式集成了Spring4.2.5+Hibernate4. ...

  3. JS:输出9*9乘法表

    <html> <head> <title>9*9 multiplication table</title> </head> <body ...

  4. How to Slove MB SD C4 Cannot Access OBD2 Port

    When using china clone mb sd connect compact 4 Multiplexer, it could not link to the car computer, M ...

  5. python基础一 day9 函数升阶(2)

    def max(a,b): return a if a>b else bprint(max(1, 2)) # 函数进阶# a = 1# def func():# print(a)# func() ...

  6. C-基础:数组名与取地址符&

    指出下面代码的输出,并解释为什么.(不错,对地址掌握的深入挖潜) main() { ]={,,,,}; ); printf(),*(ptr-)); } 输出:2,5     *(a+1)就是a[1], ...

  7. 深度学总结:skip-gram pytorch实现

    文章目录 skip-gram pytorch 朴素实现网络结构训练过程:使用nn.NLLLoss()batch的准备,为unsupervised,准备数据获取(center,contex)的pair: ...

  8. 【简●解】[USACO] 照片Photo

    [简●解][USACO] 照片Photo [题目大意] 在\(1\)~\(N\)的序列上有\(M\)个区间,使得这\(M\)个小区间每个覆盖了且仅覆盖了一个点,求最多点数,如果无解,输出\(-1\). ...

  9. Python自动化测试框架——概述

    #使用import import unittest #测试用例TestCase ''' 一个测试用例时一个完整的测试流程,包括了环境准备SetUp,测试执行Run,测试环境还原TearDown 一个测 ...

  10. nginx+tomcat实现简单的负载均衡

    host1:10.0.0.10(部署nginx和tomcat) host2:10.0.0.11(部署tomcat) 平台环境(2主机一样) [root@smp ~]# uname -r3.10.0-8 ...