Skip to content

Commit b7fcf02

Browse files
committed
📖redis
1 parent 340c3a1 commit b7fcf02

File tree

13 files changed

+1297
-1031
lines changed

13 files changed

+1297
-1031
lines changed

docs/.DS_Store

0 Bytes
Binary file not shown.

docs/.vuepress/dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Subproject commit 36ece2fca98c2db95ee0d83c9ab60dfde7ff51ed
1+
Subproject commit 2542b2edab71bdb62abf61febd50e06ec1196429

docs/data-management/.DS_Store

0 Bytes
Binary file not shown.

docs/data-management/Redis/Redis-Datatype.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ C 语言使用的这种简单的字符串表示方式, 并不能满足 Redis
182182
183183
- **编码方式**:
184184
- **int**:当值可以用整数表示时,Redis 会使用整数编码。这样可以节省内存,并且在执行数值操作时更高效。
185+
- **embstr**:这是一种特殊的编码方式,用于存储短字符串。当字符串的长度小于或等于 44 字节时,Redis 会使用 embstr 编码。只读,修改后自动转为 raw。这种编码方式将字符串直接存储在 Redis 对象的内部,这样可以减少内存分配和内存拷贝的次数,提高性能。
185186
- **raw**:当字符串值不是整数时,Redis 会使用 raw 编码。raw 编码就是简单地将字符串存储为字节序列。Redis 会根据客户端发送的字节序列来存储字符串,因此可以存储任何类型的数据,包括二进制数据。
186-
- **embstr**:这是一种特殊的编码方式,用于存储短字符串。当字符串的长度小于或等于 39 字节时,Redis 会使用 embstr 编码。这种编码方式将字符串直接存储在 Redis 对象的内部,这样可以减少内存分配和内存拷贝的次数,提高性能。
187187
188188
> 可以通过 `TYPE KEY_NAME` 查看 key 所存储的值的类型验证下。
189189
@@ -289,6 +289,37 @@ Redis 使用的是 **哈希表(Hash Table)** 来存储 `Hash` 类型的数
289289
- **哈希表**:采用 **开地址法** 来处理哈希冲突。每个 `Hash` 存储为一个哈希表,哈希表根据一定的哈希算法将键映射到一个位置。
290290
- **动态扩展**:当哈希表存储的元素数量达到一定的阈值时,Redis 会自动进行 **rehash(重哈希)** 操作,重新分配内存并调整哈希表的大小。
291291
292+
Redis 字典由 **嵌套的三层结构** 构成,采用链地址法处理哈希冲突:
293+
294+
```c
295+
// 哈希表结构
296+
typedef struct dictht {
297+
dictEntry **table; // 二维数组(哈希桶)
298+
unsigned long size; // 总槽位数(2^n 对齐)
299+
unsigned long sizemask; // 槽位掩码(size-1)
300+
unsigned long used; // 已用槽位数量
301+
} dictht;
302+
303+
// 字典结构
304+
typedef struct dict {
305+
dictType *type; // 类型特定函数(实现多态)
306+
void *privdata; // 私有数据
307+
dictht ht[2]; // 双哈希表(用于渐进式rehash)
308+
long rehashidx; // rehash进度标记(-1表示未进行)
309+
} dict;
310+
311+
// 哈希节点结构
312+
typedef struct dictEntry {
313+
void *key; // 键(SDS字符串)
314+
union {
315+
void *val; // 值(Redis对象)
316+
uint64_t u64;
317+
int64_t s64;
318+
} v;
319+
struct dictEntry *next; // 链地址法指针
320+
} dictEntry;
321+
```
322+
292323
#### 2. **Redis Hash 的内部结构**
293324
294325
Redis 中的 `Hash` 是由 **哈希表****ziplist** 两种不同的数据结构实现的,具体使用哪一种结构取决于哈希表中键值对的数量和大小。
0 Bytes
Binary file not shown.

docs/data-structure-algorithms/HashTable.md

Lines changed: 0 additions & 90 deletions
This file was deleted.

docs/data-structure-algorithms/Leetcode-dynamic-programming.md

Lines changed: 0 additions & 519 deletions
This file was deleted.

docs/data-structure-algorithms/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
![](https://images.pexels.com/photos/163064/play-stone-network-networked-interactive-163064.jpeg?cs=srgb&dl=pexels-163064.jpg&fm=jpg)
44

5+
> 关于怎么刷题的帖子:
6+
>
7+
> - 《论如何4个月高效刷满 500 题并形成长期记忆》 https://leetcode-cn.com/circle/discuss/jq9Zke/
8+
59
## 概念
610

711
**数据**(data)是描述客观事物的数值、字符以及能输入机器且能被处理的各种符号集合。 数据的含义非常广泛,除了通常的数值数据、字符、字符串是数据以外,声音、图像等一切可以输入计算机并能被处理的都是数据。例如除了表示人的姓名、身高、体重等的字符、数字是数据,人的照片、指纹、三维模型、语音指令等也都是数据。

docs/data-structure-algorithms/about-leetcode.md

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs/data-structure-algorithms/soultion/Array-Solution.md

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
---
2+
title: 数组热题
3+
date: 2025-01-08
4+
tags:
5+
- Array
6+
- algorithms
7+
- leetcode
8+
categories: leetcode
9+
---
10+
11+
![](https://cdn.pixabay.com/photo/2019/12/04/18/40/machined-parts-4673364_1280.jpg)
12+
113
### [1. 两数之和](https://leetcode-cn.com/problems/two-sum/)
214

315
> 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
@@ -77,6 +89,8 @@ public List<List<String>> groupAnagrams(String[] strs) {
7789

7890

7991

92+
93+
8094
### [128. 最长连续序列](https://leetcode.cn/problems/longest-consecutive-sequence/)
8195

8296
> 给定一个未排序的整数数组 `nums` ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
@@ -89,7 +103,7 @@ public List<List<String>> groupAnagrams(String[] strs) {
89103
> 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
90104
> ```
91105
92-
**思路**:哈希表
106+
**思路**:哈希表,**每个数都判断一次这个数是不是连续序列的开头那个数**
93107
94108
```java
95109
public int longestConsecutive(int[] nums) {
@@ -125,6 +139,51 @@ public int longestConsecutive(int[] nums) {
125139
126140

127141

142+
### [560. 和为 K 的子数组](https://leetcode.cn/problems/subarray-sum-equals-k/)
143+
144+
> 给你一个整数数组 `nums` 和一个整数 `k` ,请你统计并返回 *该数组中和为 `k` 的子数组的个数*
145+
>
146+
> 子数组是数组中元素的连续非空序列。
147+
>
148+
> ```
149+
> 输入:nums = [1,2,3], k = 3
150+
> 输出:2
151+
> ```
152+
153+
思路:**前缀和 + 哈希表**
154+
155+
1. **遍历数组**,逐步计算前缀和(表示从数组起始位置到当前位置的所有元素之和) `prefixSum`。
156+
2. 检查哈希表中是否存在 `prefixSum - k`:
157+
- 若存在,累加其出现次数到结果 `count`。
158+
3. **更新哈希表**:将当前前缀和存入哈希表,若已存在则次数加 1。![](https://assets.leetcode-cn.com/solution-static/560/3.PNG)
159+
160+
```java
161+
class Solution {
162+
public int subarraySum(int[] nums, int k) {
163+
int count = 0;
164+
int prefixSum = 0;
165+
Map<Integer, Integer> sumMap = new HashMap<>();
166+
sumMap.put(0, 1); // 初始化前缀和为0的计数为1
167+
168+
for (int num : nums) {
169+
prefixSum += num;
170+
// 检查是否存在前缀和为 prefixSum - k 的键
171+
if (sumMap.containsKey(prefixSum - k)) {
172+
count += sumMap.get(prefixSum - k);
173+
}
174+
// 更新当前前缀和的次数
175+
sumMap.put(prefixSum, sumMap.getOrDefault(prefixSum, 0) + 1);
176+
}
177+
return count;
178+
}
179+
}
180+
```
181+
182+
- **时间复杂度**:O(n),每个元素遍历一次。
183+
- **空间复杂度**:O(n),哈希表最多存储 n 个不同的前缀和。
184+
185+
186+
128187
### [14. 最长公共前缀](https://leetcode.cn/problems/longest-common-prefix/)
129188

130189
> 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 `""`
@@ -347,7 +406,7 @@ public int maxArea(int[] height){
347406
**思路**:「连续」子数组,题目要求的是返回结果,用 [动态规划、分治]
348407
349408
```java
350-
public static int maxSubArray3(int[] nums) {
409+
public static int maxSubArray(int[] nums) {
351410
//特判
352411
if (nums == null || nums.length == 0) {
353412
return 0;
@@ -381,6 +440,59 @@ public int maxSubArray(int[] nums) {
381440
382441

383442

443+
### [56. 合并区间](https://leetcode.cn/problems/merge-intervals/)
444+
445+
> 以数组 `intervals` 表示若干个区间的集合,其中单个区间为 `intervals[i] = [starti, endi]` 。请你合并所有重叠的区间,并返回 *一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间*
446+
>
447+
> ```
448+
> 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
449+
> 输出:[[1,6],[8,10],[15,18]]
450+
> 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
451+
> ```
452+
453+
思路:
454+
455+
1. **排序** 将区间按起始位置升序排列,使可能重叠的区间相邻,便于合并操作
456+
457+
![](https://pic.leetcode-cn.com/50417462969bd13230276c0847726c0909873d22135775ef4022e806475d763e-56-2.png)
458+
459+
2. **合并逻辑**
460+
461+
**遍历判断**:依次遍历排序后的区间,比较当前区间与结果列表中的最后一个区间是否重叠:
462+
463+
- 重叠条件:当前区间起始 ≤ 结果列表中最后一个区间的结束。
464+
- 合并操作:更新结果列表中最后一个区间的结束值为两者的最大值。
465+
- **非重叠条件**:直接将当前区间加入结果列表
466+
467+
```java
468+
public int[][] merge(int[][] intervals) {
469+
// 边界条件:空数组直接返回空
470+
if (intervals.length == 0) return new int[0][];
471+
472+
// 按区间起始点升序排序
473+
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
474+
475+
// 结果列表
476+
List<int[]> merged = new ArrayList<>();
477+
merged.add(intervals[0]); // 初始化第一个区间
478+
479+
for (int i = 1; i < intervals.length; i++) {
480+
int[] last = merged.get(merged.size() - 1);
481+
int[] current = intervals[i];
482+
483+
if (current[0] <= last[1]) { // 重叠,合并区间
484+
last[1] = Math.max(last[1], current[1]); // 更新结束值为较大值
485+
} else { // 不重叠,直接添加
486+
merged.add(current);
487+
}
488+
}
489+
490+
return merged.toArray(new int[merged.size()][]); // 转换为二维数组
491+
}
492+
```
493+
494+
495+
384496
### [283. 移动零](https://leetcode-cn.com/problems/move-zeroes/)
385497

386498
> 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

0 commit comments

Comments
 (0)