Skip to content

Commit

Permalink
更新HashMap
Browse files Browse the repository at this point in the history
  • Loading branch information
EchoHou2000 committed Nov 9, 2023
1 parent 2c01368 commit 9595be3
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 21 deletions.
18 changes: 0 additions & 18 deletions src/posts/Java/hashmap-kuorong.md

This file was deleted.

25 changes: 25 additions & 0 deletions src/posts/Java/hashmap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
date: 2023-10-31
category:
- Java基础
tag:
- HashMap
---

# HashMap总结

HashMap实现了Map接口,Map中的数据是以(Key,Value)的形式存储的,在查找的时候,能够通过哈希函数将Key映射到哈希表中的一个索引位置,从而实现快速访问。Key不能重复,但是Value可以重复。

HashMap的**键和值都可以为null**,如果键为null,则映射到哈希表的第一个元素。

HashMap有一个初始容量和负载因子,初始容量是哈希表的初始大小,默认是16,负载因子是哈希表在扩容之前,存储的键值对数量和哈希表大小的比例,默认是0.75。

在put元素的时候,背后调用了putVal方法,**会先判断定位到的数组位置有没有元素**。如果没有元素,则直接插入。如果有元素,会**先判断Key是否相同**,如果相同就直接覆盖;如果不同,就判断当前节点是否是一个树节点,如果是就调用putTreeVal将元素添加进去,如果不是就遍历链表插入(插入的是链表尾部)。

## HashMap的底层存储

HashMap的底层是用数组实现的,当需要存储元素的时候,不断put元素进去,达到一定容量后会扩容,一是能存储的元素更多了,二是因为**位置多了,查询效率也会更快**,之前可能多个元素会通过**拉链法**放在同一个索引上,查询的时候还需要遍历链表,时间复杂度O(n),如果位置多了,一个元素占一个索引,查找的时间复杂度就是O(1)。

## 扩容机制

数组是无法自动进行扩容的,HashMap的``resize()``方法会声明一个更大容量的数组,将之前旧的小容量数组中的元素复制过去,并且重新计算hash值,**计算hash值是为了将元素分布得更均匀,减少hash碰撞**,这个计算hash值的过程是比较耗时的。
13 changes: 13 additions & 0 deletions src/posts/bian-ma-gui-fan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
date: 2023-11-1
category:
- 项目规范
---

# Vo、Dto、Entity的区别

Entity是实体类,对应数据库表中的字段和属性。

Dto是数据传输对象,对应实际需要传输的字段,是用来将Entity转换为Vo(或者Vo转化为Entity)过程中需要的中间对象,因为不是所有的接口,都需要数据库表中的所有字段,如果用Entity会造成资源的消耗,也会有安全问题。

Vo是对应前端的HTML,有一部分字段后端数据库表是没有的。
9 changes: 9 additions & 0 deletions src/posts/https-http-diff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
date: 2023-11-1
category:
- 计算机网络
tag:
- 对比
---

# TCP/IP四层模型
70 changes: 70 additions & 0 deletions src/posts/leetcode/3sum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
date: 2023-11-2
category:
- 双指针
tag:
- 中等
---

# 8.三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a ,b ,c ,使得 a + b + c = 0 。请找出所有和为 0 且 不重复 的三元组。

```
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
```

```
输入:nums = [0]
输出:[]
```

## 思路

题目可以拆解成两个要求,一个是和为0的三元组,一个是不重复的三元组,但是三元组里面的数字是可以重复的。

首先我们可以先把数字进行排序,如果三元组的第一个数字就是大于0的,那整个组肯定不满足要求,直接返回空的集合。

如果不大于0,可以固定一个数字,用双指针寻找另外两个数字,一个在i+1处,一个在数组尾处,大于0就右指针向左移动,小于0就左指针向右移动。

```java
class Solution{
public List<List<Integer>> threeSum(int[] nums){
List<List<Integer>> res = new ArrayList<>();
if(nums == null || nums.length == 0){
return res;
}
Arrays.sort(nums);
for(int i = 0;i < nums.length;i++){
if(nums[i] > 0){
return res;
}
if(i > 0 && nums[i] == nums[i-1]){
continue;
}
int l = i + 1;
int r = nums.length-1;
while(l < r){
if(nums[i] + nums[l] + nums[r] > 0){
r--;
}else if(nums[i] + nums[l] + nums[r] < 0){
l++;
}else{
res.add(Arrays.asList(nums[i],nums[l],nums[r]));
// 去重逻辑
while(l < r && nums[r] == nums[r-1]){
r--;
}
while(l < r && nums[l] == nums[l+1]){
l++;
}
l++;
r--;
}
}
}
return res;
}
}
```
Binary file added src/posts/leetcode/image-2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/posts/leetcode/image-3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/posts/leetcode/image-4.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions src/posts/leetcode/intersection-of-two-arrays-ii.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
date: 2023-11-5
category:
- 双指针
tag:
- 简单
---

# 9.两个数组的交集II

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

```
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
```

```
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
```
1 <= nums1.length, nums2.length <= 1000
## 思路

寻找两个数组中相同的元素,可以先把两个数组进行排序,然后定义两个指针,分别指向两个数组,如果相同就把对应的元素收集起来,指针继续向后移动,如果不同就调整指针位置,继续判断。

```java
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
List<Integer> list = new ArrayList<>();
for(int i = 0,j = 0;i < nums1.length && j < nums2.length;){
if(nums1[i] > nums2[j]){
j++;
}else if(nums1[i] < nums2[j]){
i++;
}else{
list.add(nums1[i]);
i++;
j++;
}
}
int[] res = new int[list.size()];
for(int i = 0;i < list.size();i++){
res[i] = list.get(i);
}
return res;
}
}
```
57 changes: 57 additions & 0 deletions src/posts/leetcode/linked-list-cycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
date: 2023-11-7
category:
- 链表
tag:
- 双指针
---

# 11.环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

![](image-4.png)

```
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
```

## 思路

可以用快慢指针,快指针每次走两步,慢指针每次走一步,如果有环,就一定相遇。那终止条件是什么呢?因为快指针每次要往后移动两步,所以fast.next肯定不为null,同理fast也不能为null。

```java
class ListNode{
int val;
ListNode next;
ListNode(){}
ListNode(int x){
val = x;
next = null;
}
}

class Solution{
public boolean hasCycle(ListNode head){
if(head == null){
return false;
}
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
return true;
}
}
return false;
}
}
```
69 changes: 69 additions & 0 deletions src/posts/leetcode/path-sum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
date: 2023-11-1
category:
- 算法
- 二叉树
tag:
- 深度优先搜索
- 回溯
---

# 7.路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

![](image-2.png)

```
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
```
## 思路

要求**根节点到叶子节点**这条路径上的节点之和,等于目标和,所以需要判断当前的节点是否是根节点。每遍历一个节点,目标和就减去节点的值,遍历到根节点时,判断这个计数器是否为0。

```java
public class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(){}
TreeNode(int val){
this.val = val;
}
TreeNode(int val,TreeNode left,TreeNode right){
this.val = val;
this.left = left;
this.right = right;
}
}

public class Solution{
// 这个函数隐含着回溯的细节,因为是把targetSum作为参数整体传进去的
// 函数结束后,targetSum的值并没有改变
public boolean hasPathSum(TreeNode root,int targetSum){
if(root == null){
return false;
}
targetSum -= root.val;
if(root.left == null && root.right == null){
return targetSum == 0;
}

if(root.left != null){
if(hasPathSum(root.left,targetSum)){
return true;
}
}
if(root.right != null){
if(hasPathSum(root.right,targetSum)){
return true;
}
}
return false;
}
}
```
63 changes: 63 additions & 0 deletions src/posts/leetcode/word-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
date: 2023-11-6
category:
- 深度优先搜索
- 二维矩阵
tag:
- 中等
---

# 10.单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

![](image-3.png)

```java
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
```

## 思路

题目要求有两点需要注意的,一是字母不允许被重复使用,所以可以定义一个boolean类型的数组,来标记二维数组中的某个元素是否被访问过。二是最后返回是否找到这个单词,可以定义一个boolean类型的数值来标记是否找到。

搜索方式可以使用深度优先搜索,一直搜,直到到头或者不满足条件再回溯,使用我们定义的boolean类型的数组来标记某个元素被访问过,回溯后,因为选择其他位置再次寻找,要再标记成未访问。

```java
class Solution{
boolean find = false;
public boolean exist(char[][] board,String word){
if(board == null || word == null){
return false;
}
int m = board.length;
int n = board[0].length;
boolean visited[][] = new boolean[m][n];
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
dfs(i,j,board,visited,word,0);
}
}
return find;
}

void dfs(int i,int j,char[][] board,boolean[][]visited,String word,int pos){
if(i < 0 || i >= board.length || j < 0 || j >= board[0].length || find || visited[i][j] || board[i][j] != word.charAt(pos)){
return;
}
if(pos == word.length()-1){
find = true;
return;
}
visited[i][j] = true;
dfs(i+1,j,board,visited,word,pos+1);
dfs(i-1,j,board,visited,word,pos+1);
dfs(i,j+1,board,visited,word,pos+1);
dfs(i,j-1,board,visited,word,pos+1);
visited[i][j] = false;
}
}
```

0 comments on commit 9595be3

Please sign in to comment.