离职时间:
离职时间:2025.5.30
先拷打了实习 * 你简历上写的实习经历是你负责公司海外网文平台和后台管理系统,能更详细说说你在里面具体做的事情吗 * 你刚刚有提到负责开发后端的一些接口、实现一些功能,你能举一个实际的接口开发过程的例子吗,比如你接到这个需求之后是怎么去思考、分析和设计的,用到了哪些组件,或者说 db,然后你是怎么去实现交互的 * 那假设这个接口的功能你这边已经开发自测好了,
拷打实习 * 介绍一下实习具体做的哪方面内容,后台方面主要参与了哪些模块 * 有参与过比如索引、推送相关的工作吗,比如关键词对小说的索引 * 你在检索小说时是直接通过数据库还是其他方式实现的 * 那比如现在有一个数据量非常大,比如说几十万字的小说,那你是如何去存储的,如何去做检索 * 你们的网文平台是 app 还是 web * 那是通过章节来加载还是通过用户
最近发生了好多事情,很累
和 C++ 相比的话 Go 最大的特点和优势自然就是语法的简洁了,比如写并发,go 自带协程和 channel,写法更直观也更简单,而 c++ 要用线程和锁自定义来写;另外像是内存管理和部署方面,go 的垃圾回收和天生的跨平台编译与容器化都很方便,不需要手动管理内存,一条命令就可以产出可执行文件,并且 go 还自带了性能分析等工具;同时 go 的性能与 c+
A:这个项目是我为我的独立游戏《月华》的联机版独立开发的后端服务器,整体是用 Go 语言的 Gin 框架和微服务架构实现的,目前主要实现了玩家的注册登录、身份认证、对战房间和卡牌核心逻辑以及实时同步的开发,我是使用 Gin 构建了 RESTful API 来和前端服务通信,通过 JWT 做身份校验,然后用 GORM 和 MySQL 来持久化玩家与进度数据,还
算法题:hot100 原题——5. 最长回文子串
所以数组是非常繁杂的,也很难用几个固定的套路去定义它,只好常刷常新啦
A:
A:微服务将单体拆成按业务能力划分的小服务,优点是强解耦、独立部署、弹性扩缩、技术栈多样、故障隔离与快速迭代,缺点包括网络延迟提升、分布式事务与一致性复杂、观测与运维门槛较高、接口管理和安全边界昂贵;每个服务是通过轻量 API 通信并独立生命周期,团队可以自主交付,但跨进程调用可能带来不可预测的延迟,服务数量激增时运维和监控成本也会激增
嗯有挺多的其实,有一次我是接到要在项目里写一个新接口的任务,但其实 mentor 给的指令和要求是比较模糊的,所以我就先自己主动去跟前端的同事沟通,询问他们对于这个接口的需求是什么,要返回什么数据然后如何请求等,然后再跟 mentor 确认了一遍实现思路之后我才真正开始写,最后因为需求比较清晰很快就写完了
多方面立体拷打项目 * 简单介绍一下你的 DDD 六边形和微服务架构的 IM 项目 * 介绍一下你从 MVC 转型到 DDD 的构思 * 你在做架构转型时遇到的最麻烦的一个点是什么,有没有遇到比较典型的一些困难 * 微服务你分了哪几块呢? * 你在构建文件处理服务时有没有做一些优化呢?比方说对存储的一些交互 * 你提到的这个缓存我比较好奇,比如用户上传一个文
**算法不是拼智商和天赋,算法是一种可以通过科学合理的方式训练出来的能力**
开学啦,跟着周总结一起回来的当然还有碎碎念
先拷打了一下分布式缓存这个项目,顺带问了一些八股 * 做项目时有遇到哪些难点吗,以及你是如何解决的 * 你做的这个轻量级分布式缓存系统支持批量查询吗? * 那如果这个缓存系统断电了,你有考虑过一些保障机制吗,还是说重启之后数据什么的就都丢掉了 * 假如说现在给你一些时间去优化这个缓存系统的话,你觉得还有哪些可以优化的地方 * 讲讲你是怎么理解项目里用到的 S
完全自己实现: ```go func reverseWords(s string) string { length := len(s) left, right := 0, length - 1
import "strconv"
for i := 1; i <= n; i++ { pre := 0
Redis 是一个**开源的内存数据存储系统**,简单来说,它是一个非常快的数据管理工具。它通常被用作:
以下命令操作环境均为 WSL 上的 Ubuntu
**Shell**:是一个**命令解释器**,负责将用户输入的命令翻译为系统能够执行的操作,提供了一种与操作系统内核交互的方式,Linux中使用的是**Bash**(Bouren Again Shell,是Bouren Shell的增强版,广泛用于Unix和类Unix操作系统中),Windows中使用的是**PowerShell**
[链接名](链接)
A:**帧同步**是指所有客户端在相同时间步长也就是同一帧上同步输入指令或操作,然后每个客户端在本地根据这些输入来运算游戏逻辑,生产相同的状态,比如一个客户端将自己本帧内的操作发送到服务器,服务器在同步时刻将所有玩家的输入打包发送给所有客户端,
A:通过使用 atomic 头文件引入原子变量实现原子操作,保证引用计数同一时刻只能有单个线程操作,从而实现线程安全;一般来说其开销相对不高,基本上是硬件级别的低消耗,但在高并发场景下遇到多个线程对引用计数频繁修改时,可能会遇到瓶颈
go 官方文档:https://tip.golang.org/doc/gc-guide?utm_source=chatgpt.com
Go 语言的轻量级执行单元,你在代码中 `go f()` 启动的就是一个 `G`
在 Go 语言中,`switch` 语句是比传统的 `if–else` 更加简洁、灵活、功能丰富的多分支控制结构
在 Go 语言中,`struct`(结构体)是一种最常用、最基础的复合数据类型,用来**将若干个不同类型或相同类型的字段组合在一起**,形成一个新的整体
`slice` 是对数组的一个**抽象视图**,它不存储数据,而是**指向一个底层数组**,与固定大小的数组不同,`slice` 的长度可以动态改变,这使得它在实际应用中非常灵活
在 Go 语言中,`map` 是一种内置的**引用类型**,用来将“键”(`key`)映射到“值”(`value`),本质上是一种**哈希表**
通过不同的写法和变体,`for` 能够完成所有循环需求
作用:让“收尾工作”与逻辑代码紧密绑定,减少因过早 `return` 或中途出错而忘记清理资源的风险
官方文档:https://pkg.go.dev/context
在 Go 语言里,`channel`(通道)是核心的并发原语之一,用于在不同的 `goroutine` 之间安全地传递数据
`go env -w GOPROXY=https://goproxy.cn,direct`
GORM(全称「Go Object Relational Mapping」)是 Go 语言最常用的 ORM 框架之一,它能够让我们使用 Go 语言的结构体来映射数据库中的表、字段等,从而更方便地进行数据库的增删改查操作
Ubuntu 会自带 git
需要注意的是GitHub默认上传的文件不能大于100M,如果比这个大就会上传失败,需要使用一些别的方法,比如gitignore什么的(但我是直接不传那么大的了哈哈哈,所以别的方法具体我也没试过)
npm create vite@latest moonlight-radiance-web -- --template react-ts
它并不是编程性质的语言,所以相对来说上手会很快(即使没有学过cpp之类的),它更多的还是跟CSS和JavaScript一起对整个网页进行排版、布局和美化
Elasticsearch是一个**搜索和分析工具**,基于Lucene(一个搜索库)开发。它特别适合:
* 安装 Java(Elasticsearch 是基于 Java 的):`sudo apt install openjdk-11-jre` * 检查是否成功安装 Java:`java -version` * 导入公钥并安装 APT 仓库:
using namespace std;
创建一个用户表:
MySQL 在登录时会根据用户的不同而有不同的权限限制,比如 root 用户可能被限制**只能通过 sudo 方式登录**
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/string/344-reverse-string.md)
错误代码1:
```go func reverse(ch []byte) { left, right := 0, len(ch) - 1
if length < 2 { return false }
```go func reverseString(s []byte) { left, right := 0, len(s) - 1
if m == 0 { return 0 } if n < m { return -1 }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/stack-and-queue/232-implement-queue-using-stacks.md)
for _, v := range nums { freq[v]++ }
dq := make([]int, 0, k) results := make([]int, 0, length - k + 1)
sudo apt update sudo apt install code sudo apt install code-insiders (如果code命令不可用就用这个)
文件描述符(fd)是一个非负整数,用于**标识和访问操作系统中的资源**(如文件、网络连接、设备等)。**每个进程都有一个文件描述符表,进程可以通过文件描述符来操作这些资源**。
`apt` 是较新的工具,可以看作是 `apt-get` 的升级版,输出信息会更直观易读,下载速度也会更快,在现代 Linux 系统中是首选命令
one loop per thread的含义: one loop per thread是muduo的一个设计理念,即每个EventLoop只在它所属的单独线程中运行。这意味着同一个EventLoop的所有操作都在同一个线程中完成,从而简化了并发问题,不需要锁来保护EventLoop本身的数据结构。 主线程(main reactor)只处理新连接事件,然后分发
示例:
它实现了**双向链表**(Doubly Linked List)的数据结构
也是一种关联式容器,有没有multi的机制也跟set相同。
通常用法为 `std::pair<T1, T2>`,其中 `T1` 和 `T2` 表示两个不同的数据类型
是一种关联式容器,set不允许容器中有重复的元素,即使调用插入不会报错,但实际并不会被插入,但multiset允许存在重复的元素。
通过vector和deque容器,实现对于五个人的随机打分(**共十位评委**),在去掉一个最高分和一个最低分后,得出每个人最终的平均分,并打印输出
与传统的数组不同,vector 的大小可以**动态调整**,能够根据需要自动扩展或缩小
它保存了函数的地址,并允许**通过指针来调用函数**
>左值和右值都是表达式的属性,通常出现在表达式的左侧和右侧 > >左值:表示**对象的身份**,如变量、函数名 > >右值:表示**对象的值**,如代数运算表达式、匿名的lambda表达式(临时对象)
异常安全(Exception Safety): 指的是在发生异常时,程序或组件仍能维持良好状态,不会泄漏资源或处于不一致状态。RAII的广泛使用也有助于实现异常安全。当异常抛出时,栈展开会调用对象的析构函数,从而确保资源释放,保证程序不崩溃或资源不遗失。
对于不能随机访问的数据结构来说,sort算法是不能使用的,此时应使用该种容器自带的排序算法。
不可分割性:一个原子操作在执行时被视为一个整体,期间不会被其他操作打断。无论是成功还是失败,整个操作要么全部完成,要么全部不发生。
它允许你将**任何可调用对象**(如普通函数、lambda表达式、函数指针、成员函数指针等)存储在一个对象中。`std::function`可以接受多种类型的函数,并提供了**统一的调用接口**。
智能指针是封装了原始指针的类,提供了自动内存管理的机制,它们通过 **RAII**(Resource Acquisition Is Initialization,资源获取即初始化)原则,确保资源在不再需要时自动释放,从而避免手动管理内存的复杂性和错误
互斥锁是
相比传统的 `rand()`,这种方式具有:
例如:
constexpr 是“constant expression”(常量表达式)的缩写。它用于声明和定义可以在编译时求值的变量和函数。这意味着这些变量和函数的值在编译阶段就已确定,不需要在运行时计算,从而提高了程序的性能和效率。
在C++中,explicit关键字用于构造函数或者单参函数声明处,以防止编译器进行隐式类型转换。当我们在类的头文件中声明构造函数时,如果希望该构造函数不能被隐式调用(例如不能用ClassName c = value;这种隐式转换方式来构造对象),就需要在声明时加上explicit。
`std::forward` 和其他类似工具(如`std::move`)都在 **`<utility>`** 头文件中,使用时需要包含。
// 普通写法: int x = someFunction(); if (x > 0) { // ... }
`new int[10]` 会在堆上分配一个大小为 10 的整型数组,并返回一个指向数组第一个元素的指针。
如果函数声明为 `noexcept`,它表示函数内部不会抛出异常。
模板是 C++ 提供的**泛型**编程工具,用来**编写通用代码**,通过模板,你可以为不同的数据类型编写通用的算法或类,而无需重复代码
typedef std::function<void()> Function;
主要思想是利用两个指针(或称“变量索引”)在数据结构(通常为数组、链表或字符串)上进行遍历
它的目标是**快速定位一个目标元素在数组中的位置**,基本前提是数组必须已经排序,否则二分查找无法正确地工作
在一个待排序序列里,元素往往不仅有用来比较大小的“关键字”,还附带其他属性,例如一组学生记录按成绩排序,成绩相同的同学原本在名单中的先后顺序就体现了他们在班级花名册中的位置
换句话说,时间复杂度告诉我们一个算法运行多少步(或基本操作次数)随着问题规模 n 变化的**趋势**
* **连续内存存储**: 数组在内存中占用一块**连续**区域,每个元素的存储位置可以通过起始地址加上偏移量计算得到 * 所以我们不能单独删除数组中的某个元素,只能**覆盖**,也就是**移动其他元素的地址** * **下标**:数组的下标是**从0**开始的 * **固定大小**: 在大多数**静态数组**实现中(如 C 语言的数组、C++ 中的传统数组
它的**基本特性**包括:
需要将 `key` 映射到 `[0, N)` 的整数范围,其中 `N` 是哈希表的桶(bucket)数量
主要类型有:
int main() { std::stack<int> st; // 底层默认是 deque<int> st.push(10); // 压入元素 st.push(20); std::cout << "栈顶元素: " << st.top() << "\n"; // 20 st.pop(); // 弹出 20 std::cout << "弹出后栈顶: " <<
从最底层来看,字符串其实就是**一段有序的字符序列**(在计算机中通常用字节序列或 Unicode 码点序列来表示),并且会以某种方式标明“结束”或“长度”
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int slow = 0; int sum = 0; int results = INT_MAX; //宏 int length = 0;
class Solution { public: int removeDuplicates(vector<int>& nums) { int slow = 0; //没有修改初始值,导致数组索引越界 for (int fast = 0; fast < nums.size(); fast++) //没有修改初始值,导致数组索引越界 { if (nums[fas
class Solution { public: int removeElement(vector<int>& nums, int val) { int slow = 0; //创建慢指针 for (int fast = 0; fast < nums.size(); fast++) { if (nums[fast] != val) //快指针先遍历 { nu
class Solution { public: void moveZeroes(vector<int>& nums) { int slow = 0; for (int fast = 0; fast < nums.size(); fast++) { if (nums[fast] != 0) { swap(nums[slow], nums[fast]); //
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { int Left = findLeftBoundary(nums, target); int Right = findRightBoundary(nums, target); if (Left =
class Solution { public: int searchInsert(vector<int>& nums, int target) { int left = 0; //和上一题代码基本没有什么大变化 int right = nums.size() - 1; while (left <= right) { //为了防止int越界,先计算左右边界的
class Solution { public: bool isPerfectSquare(int num) { int square = 0; if (num < 2) { square = num; } int left = 1; int right = num / 2; while (left <= right) { int mid = left +
class Solution { public: vector<vector<int>> generateMatrix(int n) { // 初始化一个二维数组,这里是嵌套的,仔细分析即可弄清楚逻辑 // 有 n 行个 vector,每个 vector 有 n 列,每列都初始化为 0 vector<vector<int>> matrix(n, vector
class Solution { public: int mySqrt(int x) { if (x < 2) //此时无论什么数都会直接返回1 { return x; } int left = 1; //防止出现0在分母 int right = x / 2; //提前缩小范围,提升效率 int result = 0; while (left <= righ
class Solution { public: int search(vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; //通过vector自带的size函数得到数组终点位置 while(left <= right) { // (right - left)
class Solution { public: vector<int> sortedSquares(vector<int>& nums) { int i = 0; while (i < nums.size()) { nums[i] = nums[i] * nums[i]; //溢出越界了 } int right = 0, left = 1; while (
这道题主要是对**二分查找**概念的检验,以及如何在 cpp 中实现二分查找算法,通过将基本想法转化一下可得下面的细分步骤: - 创建 left、right 变量用于记录数组起始和结束位置 * left 初始为 0 * right 初始为数组长度减一 - 利用 while 循环,仅当 **left <= right** 时才进入 * 这里考虑使用左闭右闭区间
func backtrack(s string, results *[][]string, path []string, start int) { if start == len(s) { temp := make([]string, len(path)) copy(temp, path) *results = append(*results, temp)
mapping := map[byte]string{ '2': "abc", '3': "def", '4': "ghi", '5': "jkl", '6': "mno", '7': "pqrs", '8': "tuv", '9': "wxyz", }
return results }
```
func combinationSum(candidates []int, target int) [][]int { sort.Ints(candidates)
func combinationSum2(candidates []int, target int) [][]int { sort.Ints(candidates)
func backtrack(nums, path []int, res *[][]int, used []bool) { if len(path) == len(nums) { temp := make([]int, len(path)) copy(temp, path) *res = append(*res, temp) }
func permuteUnique(nums []int) [][]int { sort.Ints(nums) var res [][]int var path []int used := make([]bool, len(nums)) backtrack(nums, path, &res, used) return res }
func backtrack(nums, path []int, res *[][]int, start int) { if len(path) >= 2 { temp := make([]int, len(path)) copy(temp, path) *res = append(*res, temp) }
dp := make([]bool, cap + 1) dp[0] = true for _, w := range stones { if w > cap { continue }
func backtrack(nums, path []int, res *[][]int, start int) { temp := make([]int, len(path)) copy(temp, path) *res = append(*res, temp)
func subsetsWithDup(nums []int) [][]int { var res [][]int var path []int sort.Ints(nums) backtrack(nums, path, &res, 0) return res }
func restoreIpAddresses(s string) []string { var results []string var path []string backtrack(&results, path, 0, s) return results }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/backtracking/77-combinations.md)
return isMirror(root.Left, root.Right) }
var results [][]int queue := []*TreeNode{root} // 由于传入的 root 就是指针类型,这里也要用指针类型
queue := []*TreeNode{root} depth := 0
idxMap := make(map[int]int, n) for i, v := range inorder { idxMap[v] = i }
var results [][]int queue := []*TreeNode{root}
func build(nums []int, l, r int) *TreeNode { if l > r { return nil }
func checkHeight(node *TreeNode) int { if node == nil { return 0 }
queue := []*TreeNode{root} depth := 0 levels := 0
remaining := targetSum - root.Val
func connect(root *Node) *Node { if root == nil { return nil }
return results } ```
var results []int results = append(results, postorderTraversal(root.Left)...) results = append(results, postorderTraversal(root.Right)...) results = append(results, root.Val)
var results []int queue := []*TreeNode{root}
count := 0 queue := []*TreeNode{root}
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { for root != nil { if p.Val < root.Val && q.Val < root.Val { root = root.Left } else if p.Val > root.Val && q.Val > root.
l := lowestCommonAncestor(root.Left, p, q) r := lowestCommonAncestor(root.Right, p, q)
func (s *myStack) Push(val int) { s.data = append(s.data, val) }
var sum int
func levelOrder(root *Node) [][]int { if root == nil { return nil }
if key < root.Val { root.Left = deleteNode(root.Left, key) return root } if key > root.Val { root.Right = deleteNode(root.Right, key) return root }
func bfs(node *TreeNode, arr *[]int) { if node == nil { return }
var v int queue := []*TreeNode{root}
import "math"
if root2 == nil { return root1 }
var results []float64 queue := []*TreeNode{root}
maxIdx := 0 for i, _ := range nums { if nums[maxIdx] < nums[i] { maxIdx = i } }
if root.Val < low { return trimBST(root.Right, low, high) } if root.Val > high { return trimBST(root.Left, low, high) }
switch { case root.Val == val: return root case root.Val > val : return searchBST(root.Left, val) default: return searchBST(root.Right, val) } } ```
if root.Val > val { root.Left = insertIntoBST(root.Left, val) } else { root.Right = insertIntoBST(root.Right, val) }
var results []int results = append(results, inorderTraversal(root.Left)...) results = append(results, root.Val) results = append(results, inorderTraversal(root.Right)...)
var prev *TreeNode
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/binary-tree/144-binary-tree-preorder-traversal.md)
queue := []*TreeNode{root}
func (q *myQueue) Push(v int) { q.data = append(q.data, v) }
for i := 0; i < len(s); i++ { for j := m; j >= 1; j-- { if s[i] == t[j - 1] { dp[j] += dp[j - 1] } } }
for i := 1; i < len(prices); i++ { if profit < prices[i] - minPrice { profit = prices[i] - minPrice }
for i := 1; i < len(prices); i++ { preCash, preHold := cash, hold cash = max(preCash, preHold + prices[i]) hold = max(preHold, preCash - prices[i]) }
buy1, sell1 := -prices[0], 0 buy2, sell2 := -prices[0], 0
for i := 1; i <= n; i++ { for _, w := range wordDict { lw := len(w) if i >= lw && dp[i - lw] && s[i - lw : i] == w { dp[i] = true } } }
if k >= n / 2 { ans := 0 for i := 1; i < n; i++{ diff := prices[i] - prices[i - 1] if diff > 0 { ans += diff } } return ans }
return pre1 } ```
a, b := r(nums[1 :]), r(nums[: n - 1]) if a > b { return a } return b }
for i := 1; i <= n; i++ { for j := 1; j * j <= i; j++ { if dp[i] > dp[i - j * j] + 1 { dp[i] = dp[i - j * j] + 1 } } }
dp, ans := make([]int, n), 0
hold, sold, rest := -prices[0], -prices[0], 0
for _, c := range coins { for j := c; j <= amount; j++ { if dp[j] > dp[j - c] + 1 { dp[j] = dp[j - c] + 1 } } }
func dfs(node *TreeNode) (notTake, take int) { if node == nil { return 0, 0 }
for i := 2; i <= n; i++ { max := 0 for j := 1; j < i; j++ { if max < j * (i - j) { max = j * (i - j) } if max < j * dp[i - j] { max = j * dp[i - j] } } dp[i] = max }
for j := 1; j <= target; j++ { for _, n := range nums { if j >= n { dp[j] += dp[j - n] } } }
return i == len(s) } ```
dp := make([]bool, target + 1) dp[0] = true
for _, s := range strs { zeros, ones := 0, 0 for _, ch := range s{ if ch == '0' { zeros++ } else { ones++ } }
if (target + s) % 2 != 0 || abs(target) > s { return 0 } p := (target + s) / 2 dp := make([]int, p + 1) dp[0] = 1
a, b := 0, 1 for i := 2; i <= n; i++ { a, b = b, a + b } return b } ```
for _, c := range coins { for j := c; j <= amount; j++{ dp[j] += dp[j - c] } }
if currSum > maxSum { maxSum = currSum } } return maxSum } ```
for i := 1; i < m; i++ { for j := 1; j < n; j++ { dp[i][j] = dp[i - 1][j] + dp[i][j - 1] } }
for i := 1; i < m; i++ { if obstacleGrid[i][0] == 0 && dp[i - 1][0] == 1 { dp[i][0] = 1 } } for j := 1; j < n; j++ { if obstacleGrid[0][j] == 0 && dp[0][j - 1] == 1{ dp[0][j] = 1 }
for i := 0; i < n; i++ { t[i] = s[n - 1 - i] }
return ans } ```
a, b := 1, 2 for i := 3; i <= n; i++ { a, b = b, a+ b }
cash, hold := 0, -prices[0] for i := 1; i < n; i++{ newCash, newHold := cash, hold
for i := 1; i <= n; i++ { for j := m; j >= 1; j-- { if nums1[i - 1] == nums2[j - 1] { dp[j] = dp[j - 1] + 1
// 空串 -> word2[:j]:插 j 次 for j := 0; j <= m; j++ { dp[j] = j }
for i := 2; i < n; i++{ a, b = b, min(a, b) + cost[i] } return min(a, b) }
for i := 2; i <= n; i++ { total := 0 for j := 1; j <= i; j++ { total += dp[j - 1] * dp[i - j] } dp[i] = total }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/dynamic-programming/509-fibonacci-number.md)
func largestSumAfterKNegations(nums []int, k int) int { sort.Ints(nums) for i := 0; i < len(nums) && nums[i] < 0 && k > 0; i++ { nums[i] = -nums[i] k-- } sort.Ints(nums) sum := 0 i
return earn } ```
for i := 0; i < len(gas); i++ { gSum += gas[i] cSum += cost[i]
sum, right := 0, 1 for i := n - 1; i >= 0; i-- { if i < n - 1 && ratings[i] > ratings[i + 1] { right++ } else { right = 1 }
count, prediff := 1, 0 for i := 1; i < len(nums); i++ { diff := nums[i] - nums[i - 1] if (diff > 0 && prediff <= 0) || (diff < 0 && prediff >= 0) { count++ prediff = diff } }
func reconstructQueue(people [][]int) [][]int { sort.Slice(people, func(i, j int) bool { if people[i][0] != people[j][0] { return people[i][0] > people[j][0] } return people[i][1]
func eraseOverlapIntervals(intervals [][]int) int { if len(intervals) == 0 { return 0 }
end, f, count := 0, 0, 0 for i, v := range nums { if f < i + v { f = i + v }
func findMinArrowShots(points [][]int) int { if len(points) == 0 { return 0 }
func findContentChildren(g []int, s []int) int { sort.Ints(g) sort.Ints(s)
func merge(intervals [][]int) [][]int { if len(intervals) == 1 { return intervals }
func monotoneIncreasingDigits(n int) int { s := strconv.Itoa(n) digits := []byte(s) mark := len(digits) for i := len(digits) - 1; i > 0; i-- { if digits[i] < digits[i - 1] { digits
res, start, end := make([]int, 0), 0, 0 for i := 0; i < len(s); i++ { if last[s[i] - 'a'] > end { end = last[s[i] - 'a'] } if i == end { res = append(res, end - start + 1) start =
for _, v := range bills { switch v { case 5: five++ case 10: if five == 0 { return false } five-- ten++ case 20: if ten > 0 && five > 0 { ten-- five-- } else if five > 2 { five -=
var dfs func(node *TreeNode) int dfs = func(node *TreeNode) int { if node == nil { return COVERED }
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/greedy-algorithm/455-assign-cookies.md)
```go func twoSum(nums []int, target int) []int { seen := make(map[int]int, len(nums))
```go func commonChars(words []string) []string { counts := make([]int, 26)
```go import "sort"
```go func isHappy(n int) bool { visited := make(map[int]struct{})
```go func isAnagram(s string, t string) bool { counts := make([]int, 26)
```go func intersection(nums1 []int, nums2 []int) []int { if len(nums1) > len(nums2) { return intersection(nums2, nums1) }
```go func canConstruct(ransomNote string, magazine string) bool { if len(magazine) < len(ransomNote) { return false }
```go func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int { sum12 := make(map[int]int, len(nums1))
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/hash-table/242-valid-anagram.md)
if length % 2 == 1 { return false }
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func detectCycle(head *ListNode) *ListNode { fast, slow := head, head
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func getIntersectionNode(headA, headB *ListNode) *ListNode { pA, pB := hea
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNod
```cpp /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func reverseList(head *ListNode) *ListNode { cur := head var pre *ListNode
```go /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */
```cpp class MyLinkedList { private: class MyNode { public: int val; MyNode* next;
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/linked-list/203-remove-linked-list-elements.md)
l, r := 0, n - 1 lM, rM := 0, 0 water := 0
for _, x := range nums2 { for len(stack) > 0 && x > stack[len(stack) - 1] { v := stack[len(stack) - 1] stack = stack[: len(stack) - 1] next[v] = x } stack = append(stack, x) } for
for i := 0; i < n; i++ { ans[i] = -1 }
for i := 0; i < n; i++ { for len(stack) > 0 && temperatures[i] > temperatures[stack[len(stack) - 1]] { j := stack[len(stack) - 1] stack = stack[: len(stack) - 1] ans[j] = i - j } s
st := []int{} max := 0
[我的解答](https://github.com/EthanQC/my-learning-record/blob/main/data-structure-and-algorithm/problems-record/monotonic-stack/739-daily-temperatures.md)
for i := 0; i < len(s); i++ { v := s[i]
func evalRPN(tokens []string) int { stack := make([]int, 0, len(tokens))
是时候复盘一下最近的情况了
好久没有写点什么了
从老家回来了
周一就从沈阳回来了,想写点自己对于这座城市的感受
从沈阳回来啦
好久不见!
终于辞职了!
五一我是放飞自我地玩了五天,所以这周刚好相当于过渡,恢复一下正常的学习生活节奏,刚好也做做心理准备什么的
A:好的,面试官您好,我是来自深圳大学 27 届的某某,我目前是大二在读,然后我是在一家主营业务是海外网文平台的公司做后端开发岗位的实习生,我主要是负责公司的几个代码仓的维护和开发一些新接口
* **简历上自己写的东西一定要非常熟悉**,面试官问了不能答不出来也不要含糊不清 * 面经具有多样性,仅供参考,重心还是要自己的基础扎实,再去看别人的面经 * 可以用 ai 模拟面试
A:面试官您好,我是来自深圳大学电子信息工程学院的大二学生xxx,我目前是在一家小厂的后端开发岗位实习,另外还参加了清华人机交互实验室的水木心育项目的游戏开发实习,是远程的,同时我自己还有一个独立游戏项目正在开发
上周回家了
公司搬到了我小学和初中旁边
我真是没救了
周末降温了
幸福的上午
这周的心情挺奇怪的
坐我旁边的前端实习生的 mentor 经常带着口罩,坐在工位上也带
e宝,e宝
感觉自己最近的阅读量好大
要学的 * cpp ⭐⭐⭐⭐ * 现代 cpp 特性复习,包括智能指针、Lambda 表达式、移动语义、性能分析、内存优化、原子操作、并发与多线程编程等 * 熟悉封装、继承、多态等 OOP 特性以及 STL 常用容器(如 vector、map、set) * 考虑要不要看底层实现,尽量把这些东西都用到项目中 * go ⭐⭐⭐⭐ * map, struct, s
深圳其实哪都挺好的,就是有三点我一直很讨厌
三月快乐
终于!周五了!!
又是无聊的一天
让自己意识到自己其实不喜欢给别人敲代码
随着上班的进行,虽然只是第二天,但我已经熟练掌握了一些摸鱼的技巧
今天是我上班的第一天
寒假要结束啦,明天就开学了
今天收到了密纸科技,就是我之前说线下面试然后面试官人很好的那家创业小厂,的实习生offer
我又来啦,最近做了挺多事情的,心情和状态也起起伏伏,但总体还是在慢慢走向正轨的
抱歉啊啊啊啊,又这么久没更新
新年快乐!! 最近在过年所以没有写也没有更新这个仓库,整体来说这个年过得还是很开心的~ 红包收了不少,好吃的也吃了不少,哈哈哈哈哈哈哈哈哈哈
好几天没写了啊啊
今天总算把昨天的内容弄完了啊啊啊,搞的我昨天都忘记写这个了
今天上午和中午把昨天剩的两道题同步完了,然后下午去上计网,在课上把第四章啃完啦,开心!!哈哈哈哈哈哈,今天下午效率还不错,我甚至还想继续看第五章,感觉计网还是很有意思的,只是有些知识确实有点晦涩而且描述的也很抽象,然后有点难记住,所以我是准备这周之后吧(或者周天期中考完),就开始看计网的八股并同步记录,本来是想看计网书上每章对应的复习题来准备的,但貌似不如直
今天效率比较慢,主要还是因为!早八!啊啊啊啊啊啊啊!!!
今晚啃的是C++ primer plus,之前是就看过前面一点的,所以现在是到了第三章,然后下午是在啃计网,目前到第四章,还没开始看第四章网络层的内容
关于tennis项目,准备是有空的话再抽时间去看一下安卓端的代码,然后慢慢学,目前不准备把重心放这个上面啦,因为本身这个项目重点也偏算法,更何况他们已经用Java重写了一遍,这就导致跟我的方向和技术栈完全不匹配了,但我也不会直接退出,还是会看他们后面需要人做什么,然后我再做一些力所能及的事情吧
昨晚半夜十二点突发奇想,跟舍友一起去吃海底捞,回到宿舍睡觉已经是三点多了,然后今天早上十点又去上课,在课上复习大物,下午是大物实验,做完实验就去买了杯瑞幸,因为中午也没来得及睡觉
终于想起来这个仓库了,从7号考完期末之后就一直玩到现在,满打满算竟然刚好十天,也确实该恢复学习的节奏了
今天另一个重大举动是,决定了webServer项目后续的方向,我是准备采用一种**站在巨人的肩膀上**的方式,对服务器的各个模块进行评估,然后选择当前业界内最好的解决方案,进行学习和使用,包括阅读源码、编写统一接口、微服务什么的,我是感觉只有这样才能真正拯救这个已经烂到不能再烂大街的项目,而且真正写好之后,也能给我自己用来做游戏后端
今天主要是学习了set和map这两个容器,并敲了一个小练习。
今天还在逐步适应和恢复状态中~
今天把操作系统目前有的知识都整理好啦,就是epoll、多路复用I/O那些,后面会随着学习进度慢慢扩充的!
A:面试官您好,我是来自深圳大学 27 届的某某,我的专业是电子信息工程,我目前是大二在读,然后在一家主营业务是海外网文平台的公司做后端开发的实习生,然后我自己也参加了清华大学人机交互实验室的远程实习项目,在里面主要是做心理学和游戏开发相关的东西,然后我自己目前的话也有一个独立游戏正在早期开发阶段,大概情况就是这样
A:面试官您好,我叫某某,我来自深圳大学,我是 27 届,我的专业是电子信息工程,目前我是在一家主营业务是海外网文平台的公司做后端开发岗位的实习生,我个人目前的技术栈的话,我是学 C++ 出身,然后大概在去年十一月十二月的样子接触到 go 语言,我个人主要是想往后端发展,所以开始用 go 语言写一些项目,然后我目前实习的这个公司他们的项目主要是用 php 来
最近应该会把这个仓库大改造一下,因为现在这样有点混乱,虽然是以时间为顺序的,但其实非常不方便查找,而我建立这个仓库的初衷的一部分其实就是让我能在忘了某些知识的时候快速找到符合我自己学习习惯的解答,而这点恰好是gpt很难做到的(往往需要先做预设或者详细的prompt)
哈哈哈哈哈哈哈哈哈哈哈哈哈哈
这两天主要是在学HTML和flask(python下的一个轻量级后端框架),还是没有机会而且也不太想就是花特别特别多时间去每天都详细记录,所以昨天才没发,而且感觉发多了的话,也没有什么质量啊哈哈哈哈
先来说一下周末这两天在做的事情:
因为今天双城之战2更新了,而且在第四集第五集Jinx终于被认可被治愈了啊啊啊😭😭😭
昨天因为玩游戏太上头了所以没有更新哈哈哈,实在是太抱歉了(在平衡自己的情绪👉👈)
我是准备用这个项目来帮助自己快速学习操作系统、Linux、MySQL和前端,我应该会把这个项目扩展成全栈的,但具体网站要放什么还没想好,同时也在想要不要干脆弄个小页游出来
其实原因就是看双城之战导致想起来了之前的一些对我来说很痛苦的回忆
今天上午考完的,然后今天剩下的时间就是玩游戏、健身房(边健身边看双城之战,好好看啊啊啊),吃火锅,玩游戏,大扫除
昨天是这样,上午去关注特朗普和美国大选了,然后冲浪就导致上午和中午没咋学,然后下午去看哈利波特啦,还是很好看!!只是这个第五部真的紧张感越来越强了,回来吃完饭之后是紧急赶了一份后端实习的简历出来,差不多到九点多快十点,然后就被朋友拉去打cs2和lol(端游)了,后面更是发现自己完全不适合这俩游戏
唉,今天不知道为什么就是有一点那种莫名其妙的疲惫,但明明也没做什么,上午上数电在复习大物(因为感觉数电是期末很好速成的样子,我们模电数电合起来成一门课了,期末占比也不高),中午睡了一觉但一直被宿舍楼旁边最近开始在装修的一个废弃了好多年的旧食堂吵(可能是疲惫的根源),下午一直在探索各种开源社区和开源项目,因为前几天看到了一个帖子说,如果能在大的开源项目里多贡献
今天主要是闲暇时间写了两道算法题,继续数组往下写的,剩下的时间都在复习+调整情绪,下午去看哈利波特第四部啦,就是火焰杯,看得很开心!!每周最快乐的时间真的就是看哈利波特了,真的好喜欢
今天主要是把beginner教程全看完了,主要是在用GitHub的托管功能卡了我一会,不得不吐槽一下GitHub这个文件管理功能真的很混乱,哪怕想搞的好一点都很难
今天进度很不错!上午去上课啦,然后下午和晚上把HTML、CSS、JavaScript的basics都看完了,晚上还去泡了两个小时的健身房,然后中间各种小时间也休息娱乐了,很开心很充实!
上午去上数电了,因为要小测就一直在学前面的内容,没能自学成功,下午是大物实验,做完实验又去体测,整到五点又跟舍友一起去楼下开的火锅搓了一顿,哈哈哈哈哈哈,吃得很开心,然后回来就是娱乐、休息、洗澡、学习
其实我挺讨厌这种感觉的,就是某件事情的进度一直被其他各种莫名其妙且对这件事没有任何帮助的事所拖累着,这就会让我持续性地焦虑,因为我还没想好具体的路究竟该怎么走
昨天主要是继续学完了STL的基础,比如仿函数、谓词等概念,以及一些基本算法库中的算法;另外是对于后面的学习规划做了一些探索和调整,中间因为要学的东西太多了还崩溃了好几次哈哈哈哈哈哈哈
现在已经是23:57了,我深刻反思,明天一定补上今天的内容
看到有几位感觉很厉害的大佬开始关注了我的账号,属实有些惶恐哈哈哈哈哈,也一度想过要不要用英语来写,但还是让我再纠结一下吧。
我是那种学得慢忘得快(bushi)的选手,刚刚甚至忘了自己学过string和queue哈哈哈哈哈哈,所以这也是记录的意义——让我自己忘得慢一些,忘了还能翻翻自己写的东西。