2026-02-080

相关信息

es基础知识点学习(Elasticsearch)

为什么要使用es

  • 先抛出一个问题

如果数据库已经能 like '%关键词%' 查询了,为什么还要 ES?

  • 可以总结为三点
    • 海量数据(千万、上亿)
    • 高性能搜索(毫秒级)
    • 复杂搜索需求(全文检索、相关性排序、高亮、分词)

ES的核心概念

elasticsearchmysql
Index(索引)database
Document(文档)row(行)
Field(字段)column(行)
Mapping表结构
Shard(分片)数据拆分
Replic(副本)数据备份

es为什么写入1秒才能被检索到

因为 Elasticsearch 采用 Near Real-Time 机制。

写入数据后不会立即生成倒排索引,而是先写入内存 buffer 和 translog。 只有在 refresh(默认1秒)时,才会生成 segment,使数据可搜索。

这样设计是为了减少频繁构建索引的开销,提高写入性能。

二叉搜索树删除节点实现

二叉搜索树(左子树比根节点小,右子树比根节点大) 里面查找并删除一个值和节点, 删除后保持搜索树结构,返回树的跟节点,假定树节点的值不重复

golang实现

js
type TreeNode struct { Val int Left *TreeNode Right *TreeNode } func deleteNode(root *TreeNode, key int) *TreeNode { if root == nil { return nil } if key < root.Val { root.Left = deleteNode(root.Left, key) } else if key > root.Val { root.Right = deleteNode(root.Right, key) } else { // 找到要删除的节点 if root.Left == nil { return root.Right } if root.Right == nil { return root.Left } // 左右子树都存在:找右子树最小节点 minNode := root.Right for minNode.Left != nil { minNode = minNode.Left } root.Val = minNode.Val root.Right = deleteNode(root.Right, minNode.Val) } return root }

每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73] 输出: [1,1,4,2,1,1,0,0] 示例 2:

输入: temperatures = [30,40,50,60] 输出: [1,1,1,0] 示例 3:

输入: temperatures = [30,60,90] 输出: [1,1,0]

js
func dailyTemperatures(temperatures []int) []int { n := len(temperatures) res := make([]int, n) stack := []int{} // 存下标 for i := 0; i < n; i++ { for len(stack) > 0 && temperatures[i] > temperatures[stack[len(stack)-1]] { prev := stack[len(stack)-1] stack = stack[:len(stack)-1] res[prev] = i - prev } stack = append(stack, i) } return res }

相关信息

算法题实现

题目一

  • 给定一个旋转的有序数组,比如{7,8,9,10,1,2,3} // 是{1,2,3,7,8,9,10}旋转之后得到的, // 在数组中查找是否存在元素key。假定数组中不存在重复元素。 golang进行实现

相关信息

本章节主要学习网络知识

短连接

  • 模式:建立连接 -> 发送数据 -> 关闭连接。
  • 背景:早期的 HTTP/1.0。每请求一个网页上的图片或 CSS,都要经历一次 TCP 三次握手和四次挥手。
  • 缺点:开销极大。频繁地创建和销毁连接非常耗费 CPU 和内存资源。

长连接

  • 模式:建立连接 -> 发送数据 -> 保持连接 -> 发送数据 -> ... -> 关闭连接。
  • 背景:HTTP/1.1 默认开启。在 HTTP Header 中加入 Connection: keep-alive。
  • 特点:
    • 复用:同一个 TCP 连接可以发送多个 HTTP 请求。
    • 半双工:虽然连接没断,但依然是“请求-响应”模式。必须客户端先问,服务端才能答。
    • 阻塞:前面的请求没处理完,后面的请求就得排队(Head-of-line blocking)

WebSocket (全双工长连接)

  • 模式:HTTP 握手升级 -> 建立持久 TCP 连接 -> 双向实时传输。
  • 背景:为了解决“服务端主动推送到客户端”的问题(如聊天、实时股票)。
  • 特点:
    • 全双工:客户端和服务器可以同时给对方发消息,不需要等对方回应。
    • 协议升级:它开始时借用 HTTP 的 80/443 端口进行握手,握手成功后就“脱离” HTTP,转为 WebSocket 协议。
    • 轻量:数据头非常小,适合频繁发送短消息。
2026-01-150

相关信息

堆栈的区别

内存分配的区别

  • 栈内存
    • 分配方式:由编译器自动分配和释放
    • 存储内容: 函数的局部变量、参数值、返回地址
    • 生长方向: 向低地址生长
    • 连续的内存区域
    • 异常类型: 栈溢出
    • 访问速度: 快
  • 堆内存
    • 分配方式: 由程序员手动申请和释放(go中的new),go中由垃圾回收期处理
    • 存储内容: 动态生成的对象,大型数组
    • 访问速度:慢(随机访问较多)
  • go中堆栈的情况

相关信息

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

js
package main import ( "fmt" ) // 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 // 最近公共祖先的定义:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x, // 满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” // 例如,如下二叉树: Integer[] levelOrder = {3,5,1,6,2,0,8,null,null,7,4}; // 3 // 5 1 // 6 2 0 8 // 7 4 type TreeNode struct { Val int Left *TreeNode Right *TreeNode } func main() { // 构建二叉树 root := &TreeNode{Val: 3} root.Left = &TreeNode{Val: 5} root.Right = &TreeNode{Val: 1} root.Left.Left = &TreeNode{Val: 6} root.Left.Right = &TreeNode{Val: 2} root.Right.Left = &TreeNode{Val: 0} root.Right.Right = &TreeNode{Val: 8} root.Left.Right.Left = &TreeNode{Val: 7} root.Left.Right.Right = &TreeNode{Val: 4} // 测试最近公共祖先 p := root.Left.Right.Left q := root.Left.Right.Right lca := lowestCommonAncestor(root, p, q) fmt.Println("最近公共祖先:", lca.Val) // fmt.Println("Hello world!") } func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { if root == nil || root == p || root == q { return root } left := lowestCommonAncestor(root.Left, p, q) right := lowestCommonAncestor(root.Right, p, q) if left != nil && right != nil { return root } if left != nil { return left } return right }
2025-12-150

相关信息

接雨水,这道题最大的问题在于理解怎么才能接到雨水

接雨水其实就是看当前位置的左右是否存在格挡,存在格挡可以存雨水,能存放的最大容积为左右出现的格挡的最大高度

第一步 声明变量初始值 left right maxLeft Maxleft res

第二步 从左右两边开始对比: for left < right {}

第三步 if height[left] < height[right] 则处理左边,否则处理右边

第四步 处理左边 如果当前位置(left)大于等于 maxLeft 则更新maxLeft 否则说明左边的高度是超出当前位置的,可以进行容积增加: maxLeft - height[left]

右边的逻辑和左边一样,发现右边的格挡更高,则增加高度差,否则更新高度最大值(当前值比maxRight更大)

js
func trap(height []int) int { left, right := 0, len(height)-1 leftMax, rightMax := 0, 0 res := 0 for left < right { if height[left] < height[right] { if height[left] >= leftMax { leftMax = height[left] } else { res += leftMax - height[left] } left++ } else { if height[right] >= rightMax { rightMax = height[right] } else { res += rightMax - height[right] } right-- } } return res }