├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── .hugo_build.lock ├── .vscode └── settings.json ├── README.md ├── archetypes └── default.md ├── assets └── css │ └── _custom.scss ├── config.toml ├── configs └── loveit.toml ├── content └── posts │ ├── Games │ ├── Overwatch │ │ └── 破坏球点位 │ │ │ ├── 66号公路.md │ │ │ ├── 伊利奥斯.md │ │ │ ├── 努巴尼.md │ │ │ ├── 哈瓦那.md │ │ │ ├── 国王大道.md │ │ │ └── 阿努比斯.md │ ├── Pokemmo │ │ ├── 捡垃圾.md │ │ ├── 搬道馆.md │ │ └── 果农.md │ ├── Super auto pets │ │ ├── 一些流派.md │ │ └── 标准包一阶.md │ ├── fm.md │ ├── ptcg │ │ ├── 简中单卡分析 │ │ │ ├── 泽.md │ │ │ ├── 苍.md │ │ │ └── 赫.md │ │ └── 繁中卡表.md │ ├── 世界弹射物语 │ │ ├── abs.md │ │ └── 杂.md │ ├── 博德之门3.md │ ├── 围棋 │ │ └── 基础知识.md │ └── 文明六 │ │ ├── 女刚果.md │ │ ├── 小技巧.md │ │ ├── 德国.md │ │ ├── 拜占庭.md │ │ └── 朝鲜.md │ ├── poetry │ ├── classical.md │ ├── modern.md │ └── 谷歌的诗 │ │ └── 巧巧红妆花间客.md │ ├── useful │ ├── Go dockerfile 通用配置.md │ ├── Minecraft 开服教程.md │ ├── Steam 开服教程.md │ ├── USB 线材详解.md │ ├── useful.md │ ├── 一些离线安装的技巧.md │ ├── 一些老是忘掉的常识.md │ ├── 云服务器能用来干啥.md │ ├── 八股文.md │ ├── 实习与项目.md │ ├── 配置 Neovim.md │ ├── 配置 Typora.md │ ├── 配置 VSCode.md │ ├── 配置 Visual Studio.md │ ├── 配置 WSL.md │ ├── 配置 WindowsTerminal.md │ └── 配置 gitbook.md │ ├── 专业 │ ├── Archive │ │ └── HomeWork │ │ │ ├── Algorithm │ │ │ ├── 报告一.md │ │ │ ├── 报告七.md │ │ │ ├── 报告三.md │ │ │ ├── 报告二.md │ │ │ ├── 报告五.md │ │ │ ├── 报告六.md │ │ │ └── 报告四.md │ │ │ ├── DataBase │ │ │ ├── ex2.md │ │ │ ├── ex3.md │ │ │ ├── ex4.md │ │ │ ├── 作业一.md │ │ │ ├── 作业三.md │ │ │ ├── 作业二.md │ │ │ └── 报告.md │ │ │ ├── OS │ │ │ ├── semester1 │ │ │ │ ├── ex1.md │ │ │ │ ├── ex3.md │ │ │ │ ├── ex6.md │ │ │ │ └── 研讨.md │ │ │ └── semester2 │ │ │ │ ├── ex1.md │ │ │ │ ├── ex2.md │ │ │ │ ├── ex3.md │ │ │ │ ├── ex4.md │ │ │ │ └── 软硬链接.md │ │ │ ├── 其他 │ │ │ ├── About Tie Breaker.md │ │ │ ├── TieBreaker 答辩.md │ │ │ ├── TieBreaker 视频稿.md │ │ │ ├── 仿生力学.md │ │ │ └── 创新项目开题.md │ │ │ ├── 前沿 │ │ │ ├── 前沿研讨.md │ │ │ └── 报告.md │ │ │ ├── 安保 │ │ │ ├── ex3.md │ │ │ ├── ex4.md │ │ │ └── 端口扫描.md │ │ │ ├── 数字图像处理 │ │ │ ├── ex │ │ │ │ ├── ex1.md │ │ │ │ ├── ex2.md │ │ │ │ ├── ex3.md │ │ │ │ ├── ex4.md │ │ │ │ └── ex5.md │ │ │ ├── homework │ │ │ │ ├── Chapter2.md │ │ │ │ ├── Chapter3.md │ │ │ │ ├── Chapter4.md │ │ │ │ ├── Chapter6.md │ │ │ │ └── Chapter8.md │ │ │ └── 题目.md │ │ │ ├── 编译原理 │ │ │ ├── Chapter1.md │ │ │ ├── Chapter2.md │ │ │ ├── Chapter3.md │ │ │ ├── 实验二.md │ │ │ ├── 实验五.md │ │ │ └── 思路.md │ │ │ ├── 计算机系统结构 │ │ │ ├── MPICH.md │ │ │ ├── OpenMP.md │ │ │ ├── benchmark.md │ │ │ ├── ex2.md │ │ │ ├── ex5.md │ │ │ ├── ex6.md │ │ │ └── 大报告.md │ │ │ ├── 计算机英语 │ │ │ ├── 1.md │ │ │ ├── 19120198-孙天野-实用计算英语作业(1000).md │ │ │ ├── 2.md │ │ │ ├── 3.md │ │ │ ├── 4.md │ │ │ ├── 5.md │ │ │ ├── 文章.md │ │ │ └── 期末.md │ │ │ └── 计算机视觉 │ │ │ ├── ex1.md │ │ │ ├── ex2.md │ │ │ ├── ex3.md │ │ │ ├── ex4.md │ │ │ ├── ex5.md │ │ │ ├── ex6.md │ │ │ ├── ex7.md │ │ │ ├── ex8.md │ │ │ └── ex9.md │ ├── C# │ │ └── BasicGrammar.md │ ├── Courses │ │ ├── DigitalImageProcessing.md │ │ ├── Operating System │ │ │ ├── OS2.md │ │ │ ├── OS22.md │ │ │ ├── OperatingSystem1.md │ │ │ └── OperatingSystem2.md │ │ ├── 实用计算机英语.md │ │ ├── 数据库原理 │ │ │ ├── 数据库原理一.md │ │ │ └── 数据库原理二.md │ │ ├── 数据结构.md │ │ ├── 概率论与数理统计 │ │ │ ├── 1. 概念.md │ │ │ ├── 2. 随机变量及其分布.md │ │ │ ├── 3. 多维随机变量及其分布.md │ │ │ ├── 4. 随机变量的数字特征.md │ │ │ ├── 5. 大数定律与中心极限定理.md │ │ │ ├── 6. 样本及抽样分布.md │ │ │ ├── 7. 参数估计.md │ │ │ └── 8. 假设检验.md │ │ ├── 离散数学 │ │ │ ├── 离散数学1 │ │ │ │ ├── 离散1-3.md │ │ │ │ ├── 离散4.md │ │ │ │ └── 离散5.md │ │ │ ├── 离散数学2.md │ │ │ └── 题型.md │ │ ├── 算法设计与分析.md │ │ ├── 编译原理.md │ │ ├── 计算机系统结构.md │ │ ├── 计算机组成原理 │ │ │ ├── 1. 概论.md │ │ │ ├── 2. 运算方法和运算器.md │ │ │ ├── 3. 存储器.md │ │ │ ├── 4. 指令系统.md │ │ │ ├── 5. 中央处理器.md │ │ │ ├── 6. 总线系统.md │ │ │ ├── 7. 外围设备.md │ │ │ ├── 8. 输入输出系统.md │ │ │ └── 捋一捋.md │ │ ├── 计算机网络 │ │ │ ├── 1. 概述.md │ │ │ ├── 2. 物理层.md │ │ │ ├── 3. 数据链路层.md │ │ │ ├── 4. 网络层.md │ │ │ └── 5. 运输层.md │ │ ├── 计算机视觉.md │ │ ├── 设计模式.md │ │ └── 软件工程.md │ ├── Cpp │ │ ├── STL.md │ │ ├── 类.md │ │ └── 要点.md │ ├── DataBase │ │ ├── LevelDB.md │ │ ├── MongoDB.md │ │ ├── MySQL │ │ │ ├── MVCC.md │ │ │ ├── 一些八股.md │ │ │ ├── 事务.md │ │ │ ├── 基本概念.md │ │ │ ├── 执行一条 select 语句,期间发生了什么.md │ │ │ ├── 查询练习.md │ │ │ └── 索引.md │ │ ├── Redis │ │ │ ├── 八股文.md │ │ │ └── 基本概念.md │ │ └── SQLite.md │ ├── Frontend │ │ ├── API 规范.md │ │ ├── CSS │ │ │ ├── CSS.md │ │ │ ├── Tailwind.md │ │ │ └── flex.md │ │ ├── HTML.md │ │ ├── JavaScript │ │ │ ├── BasicGrammar.md │ │ │ ├── DOM.md │ │ │ └── TypeScript.md │ │ ├── Svelte │ │ │ └── 基本语法.md │ │ ├── Vue │ │ │ ├── Pinia.md │ │ │ ├── Vue2.md │ │ │ ├── Vue3.md │ │ │ └── Vuetify.md │ │ ├── 包管理工具 │ │ │ └── yarn.md │ │ └── 框架 │ │ │ └── Vue2.md │ ├── Golang │ │ ├── Basicgrammar.md │ │ ├── Go 泛型.md │ │ ├── go test.md │ │ ├── webBackend │ │ │ └── gin.md │ │ ├── 一些八股文.md │ │ ├── 一些思考.md │ │ ├── 命名和开发规范.md │ │ ├── 常用库 │ │ │ ├── amqp.md │ │ │ ├── cobra.md │ │ │ ├── godotenv.md │ │ │ ├── gopacket.md │ │ │ ├── gprc-go.md │ │ │ ├── viper.md │ │ │ ├── websocket.md │ │ │ └── zap.md │ │ ├── 并发编程.md │ │ ├── 数据库操作 │ │ │ ├── go-redis.md │ │ │ ├── goleveldb.md │ │ │ ├── gorm.md │ │ │ └── sql.md │ │ ├── 标准库 │ │ │ ├── IO │ │ │ │ ├── bufio.md │ │ │ │ ├── fmt.md │ │ │ │ ├── io.md │ │ │ │ └── ioutil.md │ │ │ ├── context.md │ │ │ ├── exec.md │ │ │ ├── flag.md │ │ │ ├── log.md │ │ │ ├── math.md │ │ │ ├── pprof.md │ │ │ ├── rand.md │ │ │ ├── sync.md │ │ │ ├── time.md │ │ │ ├── 数据结构与算法 │ │ │ │ ├── container.md │ │ │ │ └── sort.md │ │ │ ├── 文件系统 │ │ │ │ ├── filepath.md │ │ │ │ └── os.md │ │ │ ├── 文本 │ │ │ │ ├── bytes.md │ │ │ │ ├── strconv.md │ │ │ │ ├── strings.md │ │ │ │ ├── template.md │ │ │ │ └── unicode.md │ │ │ └── 网络 │ │ │ │ ├── net.md │ │ │ │ └── 网络编程.md │ │ ├── 版本新特性.md │ │ └── 进阶 │ │ │ ├── Go 专家编程.md │ │ │ ├── Go 类型系统详解.md │ │ │ ├── Go 进阶.md │ │ │ ├── Go 高性能编程.md │ │ │ ├── channel 用例大全.md │ │ │ ├── nil 详解.md │ │ │ └── 非类型安全指针.md │ ├── Java │ │ └── BasicGrammar.md │ ├── Linux │ │ ├── Linux.md │ │ ├── shell 编程.md │ │ ├── 一些小技巧.md │ │ ├── 从零开始构建 Linux 开发环境.md │ │ ├── 命令工具 │ │ │ ├── autojump.md │ │ │ ├── bat.md │ │ │ ├── cloc.md │ │ │ ├── crontab.md │ │ │ ├── exa.md │ │ │ ├── fd.md │ │ │ ├── screen.md │ │ │ ├── sed.md │ │ │ └── tldr.md │ │ ├── 基础.md │ │ ├── 文件操作.md │ │ ├── 用户管理.md │ │ ├── 相关软件 │ │ │ ├── Linux 上的环境安装.md │ │ │ ├── NFS.md │ │ │ ├── apt-get.md │ │ │ └── oh-my-zsh.md │ │ ├── 软件操作.md │ │ └── 进程管理.md │ ├── Lua │ │ └── BasicGrammar.md │ ├── MachineLearning │ │ └── MachineLearning.md │ ├── Python │ │ ├── BasicGrammar.md │ │ ├── Crawler │ │ │ ├── BeautifulSoup4.md │ │ │ ├── PyQuery.md │ │ │ ├── RegularExpression.md │ │ │ ├── Requests.md │ │ │ ├── Selenium.md │ │ │ └── XPath.md │ │ ├── DataAnalysis │ │ │ ├── Matplotlib.md │ │ │ ├── Numpy.md │ │ │ ├── Pandas.md │ │ │ └── Seaborn.md │ │ ├── MachineLearning │ │ │ └── sklearn.md │ │ ├── Python.md │ │ ├── WEB backend │ │ │ ├── Django.md │ │ │ ├── FastAPI.md │ │ │ ├── Flask.md │ │ │ └── Pydantic │ │ │ │ ├── 01. models.md │ │ │ │ ├── 02. Fields.md │ │ │ │ ├── 10. Validators.md │ │ │ │ ├── Pydantic.md │ │ │ │ └── field types.md │ │ ├── 内建函数.md │ │ ├── 可视化 │ │ │ ├── DearPyGui.md │ │ │ ├── PyQt5.md │ │ │ ├── manim.md │ │ │ ├── rich │ │ │ │ ├── column.md │ │ │ │ ├── console markup.md │ │ │ │ ├── console.md │ │ │ │ ├── highlighting.md │ │ │ │ ├── layout.md │ │ │ │ ├── pretty printing.md │ │ │ │ ├── progress display.md │ │ │ │ ├── prompt.md │ │ │ │ ├── rich text.md │ │ │ │ ├── styles.md │ │ │ │ ├── tables.md │ │ │ │ └── 快速开始.md │ │ │ ├── tkinter.md │ │ │ └── wordcloud.md │ │ ├── 图像处理 │ │ │ └── cv2.md │ │ ├── 字节码.md │ │ ├── 常用库 │ │ │ ├── aiohttp.md │ │ │ ├── apscheduler.md │ │ │ ├── bisect.md │ │ │ ├── doctest.md │ │ │ ├── faker.md │ │ │ ├── getpot.md │ │ │ ├── importlib.md │ │ │ ├── ipdb.md │ │ │ ├── logging.md │ │ │ ├── loguru.md │ │ │ ├── pyinstaller.md │ │ │ ├── pyinstrument.md │ │ │ ├── random.md │ │ │ ├── ruff.md │ │ │ ├── sentry-sdk.md │ │ │ ├── threading.md │ │ │ ├── tqdm.md │ │ │ ├── typer.md │ │ │ └── warnings.md │ │ ├── 异步任务 │ │ │ ├── asyncio.md │ │ │ ├── celery.md │ │ │ ├── dramatiq.md │ │ │ └── 对 Python 异步思想的理解.md │ │ ├── 数据库交互 │ │ │ ├── marshmallow.md │ │ │ ├── motor.md │ │ │ ├── redis.md │ │ │ └── sqlalchemy.md │ │ ├── 标准库 │ │ │ ├── abc.md │ │ │ ├── collections.md │ │ │ ├── contextlib.md │ │ │ ├── contextvars.md │ │ │ ├── dataclasses.md │ │ │ ├── datetime.md │ │ │ ├── enum.md │ │ │ ├── inspect.md │ │ │ ├── io.md │ │ │ ├── os.md │ │ │ ├── pathlib.md │ │ │ ├── pickle.md │ │ │ ├── pytest.md │ │ │ ├── sys.md │ │ │ ├── tempfile.md │ │ │ ├── time.md │ │ │ ├── typing.md │ │ │ ├── unittest.md │ │ │ └── zipfile.md │ │ ├── 流畅的 Python.md │ │ ├── 版本新特性.md │ │ ├── 版本管理 │ │ │ ├── pyenv.md │ │ │ └── virtualenv.md │ │ ├── 特性.md │ │ ├── 设计模式 Python 实现.md │ │ ├── 进阶.md │ │ └── 配置 jupyter-lab.md │ ├── markdown.md │ ├── 专业.md │ ├── 刷题 │ │ ├── DP │ │ │ ├── 10. 正则表达式匹配.md │ │ │ ├── 139. 单词拆分.md │ │ │ ├── 152. 乘积最大子数组.md │ │ │ ├── 198. 打家劫舍.md │ │ │ ├── 2100. 适合打劫银行的日子.md │ │ │ ├── 221. 最大正方形.md │ │ │ ├── 279. 完全平方数.md │ │ │ ├── 300. 最长递增子序列.md │ │ │ ├── 309. 最佳买卖股票时机含冷冻期.md │ │ │ ├── 322. 零钱兑换.md │ │ │ ├── 337. 打家劫舍 III.md │ │ │ ├── 338. 比特位计数.md │ │ │ ├── 62. 不同路径.md │ │ │ ├── 64. 最小路径和.md │ │ │ ├── 96. 不同的二叉搜索树.md │ │ │ ├── 剑指 Offer 10- I. 斐波那契数列.md │ │ │ ├── 剑指 Offer 10- II. 青蛙跳台阶问题.md │ │ │ ├── 剑指 Offer 42. 连续子数组的最大和.md │ │ │ ├── 剑指 Offer 46. 把数字翻译成字符串.md │ │ │ ├── 剑指 Offer 47. 礼物的最大价值.md │ │ │ ├── 剑指 Offer 48. 最长不含重复字符的子字符串.md │ │ │ └── 剑指 Offer 63. 股票的最大利润.md │ │ ├── array │ │ │ ├── 136. 只出现一次的数字.md │ │ │ ├── 1546. 和为目标值且不重叠的非空子数组的最大数目.md │ │ │ ├── 16. 最接近的三数之和.md │ │ │ ├── 18. 四数之和.md │ │ │ ├── 20. 有效的括号.md │ │ │ ├── 209. 长度最小的子数组.md │ │ │ ├── 215. 数组中的第 K 个最大元素.md │ │ │ ├── 238. 除自身以外数组的乘积.md │ │ │ ├── 26. 删除有序数组中的重复项.md │ │ │ ├── 27. 移除元素.md │ │ │ ├── 283. 移动零.md │ │ │ ├── 31. 下一个排列.md │ │ │ ├── 33. 搜索旋转排序数组.md │ │ │ ├── 349. 两个数组的交集.md │ │ │ ├── 367. 有效的完全平方数.md │ │ │ ├── 384. 打乱数组.md │ │ │ ├── 42. 接雨水.md │ │ │ ├── 54. 螺旋矩阵.md │ │ │ ├── 560. 和为 K 的子数组.md │ │ │ ├── 59. 螺旋矩阵 II.md │ │ │ ├── 69. x 的平方根 .md │ │ │ ├── 904. 水果成篮.md │ │ │ ├── 977. 有序数组的平方.md │ │ │ ├── 双指针 │ │ │ │ ├── 11. 盛最多水的容器.md │ │ │ │ ├── 15. 三数之和.md │ │ │ │ ├── 75. 颜色分类.md │ │ │ │ ├── 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面.md │ │ │ │ └── 剑指 Offer 57. 和为 s 的两个数字.md │ │ │ ├── 哈希 │ │ │ │ ├── 1. 两数之和.md │ │ │ │ ├── 128. 最长连续序列.md │ │ │ │ ├── 1282. 用户分组.md │ │ │ │ ├── 454. 四数相加 II.md │ │ │ │ └── 剑指 Offer 61. 扑克牌中的顺子.md │ │ │ ├── 排序 │ │ │ │ ├── 347. 前 K 个高频元素.md │ │ │ │ ├── 56. 合并区间.md │ │ │ │ ├── 剑指 Offer 40. 最小的 k 个数.md │ │ │ │ ├── 剑指 Offer 41. 数据流中的中位数.md │ │ │ │ └── 剑指 Offer 45. 把数组排成最小的数.md │ │ │ ├── 查找 │ │ │ │ ├── 169. 多数元素.md │ │ │ │ ├── 34. 在排序数组中查找元素的第一个和最后一个位置.md │ │ │ │ ├── 35. 搜索插入位置.md │ │ │ │ ├── 4. 寻找两个正序数组的中位数.md │ │ │ │ ├── 剑指 Offer 03. 数组中重复的数字.md │ │ │ │ ├── 剑指 Offer 04. 二维数组中的查找.md │ │ │ │ ├── 剑指 Offer 11. 旋转数组的最小数字.md │ │ │ │ ├── 剑指 Offer 53 - I. 在排序数组中查找数字 I.md │ │ │ │ └── 剑指 Offer 53 - II. 0~n-1 中缺失的数字.md │ │ │ ├── 栈与队列 │ │ │ │ ├── 150. 逆波兰表达式求值.md │ │ │ │ ├── 239. 滑动窗口最大值.md │ │ │ │ ├── 剑指 Offer 09. 用两个栈实现队列.md │ │ │ │ └── 剑指 Offer 30. 包含 min 函数的栈.md │ │ │ └── 模拟 │ │ │ │ └── 48. 旋转图像.md │ │ ├── back tracking │ │ │ ├── 200. 岛屿数量.md │ │ │ ├── 2044. 统计按位或能得到最大值的子集数目.md │ │ │ ├── 216. 组合总和 III.md │ │ │ ├── 39. 组合总和.md │ │ │ ├── 399. 除法求值.md │ │ │ ├── 46. 全排列.md │ │ │ ├── 77. 组合.md │ │ │ ├── 78. 子集.md │ │ │ ├── 90. 子集 II.md │ │ │ ├── BFS │ │ │ │ └── 207. 课程表.md │ │ │ ├── DFS │ │ │ │ ├── 17. 电话号码的字母组合.md │ │ │ │ ├── 剑指 Offer 12. 矩阵中的路径.md │ │ │ │ └── 剑指 Offer 13. 机器人的运动范围.md │ │ │ ├── 剑指 Offer 34. 二叉树中和为某一值的路径.md │ │ │ ├── 剑指 Offer 36. 二叉搜索树与双向链表.md │ │ │ ├── 剑指 Offer 54. 二叉搜索树的第k大节点.md │ │ │ ├── 剑指 Offer 64. 求1+2+…+n.md │ │ │ ├── 平分物品.md │ │ │ └── 正经回溯 │ │ │ │ └── 22. 括号生成.md │ │ ├── greedy │ │ │ └── 55. 跳跃游戏.md │ │ ├── link list │ │ │ ├── 141. 环形链表.md │ │ │ ├── 142. 环形链表 II.md │ │ │ ├── 148. 排序链表.md │ │ │ ├── 19. 删除链表的倒数第 N 个结点.md │ │ │ ├── 2. 两数相加.md │ │ │ ├── 206. 反转链表.md │ │ │ ├── 21. 合并两个有序链表.md │ │ │ ├── 234. 回文链表.md │ │ │ ├── 24. 两两交换链表中的节点.md │ │ │ ├── 287. 寻找重复数.md │ │ │ ├── 剑指 Offer 06. 从尾到头打印链表.md │ │ │ ├── 剑指 Offer 18. 删除链表的节点.md │ │ │ ├── 剑指 Offer 22. 链表中倒数第 k 个节点.md │ │ │ ├── 剑指 Offer 24. 反转链表.md │ │ │ ├── 剑指 Offer 25. 合并两个排序的链表.md │ │ │ ├── 剑指 Offer 35. 复杂链表的复制.md │ │ │ └── 剑指 Offer 52. 两个链表的第一个公共节点.md │ │ ├── others │ │ │ ├── 1374. 生成每种字符都是奇数个的字符串.md │ │ │ ├── 146. LRU 缓存.md │ │ │ ├── 202. 快乐数.md │ │ │ ├── 7. 整数反转.md │ │ │ ├── 9. 回文数.md │ │ │ ├── 剑指 Offer 15. 二进制中 1 的个数.md │ │ │ ├── 剑指 Offer 16. 数值的整数次方.md │ │ │ └── 剑指 Offer 65. 不用加减乘除做加法.md │ │ ├── string │ │ │ ├── 1047. 删除字符串中的所有相邻重复项.md │ │ │ ├── 12. 整数转罗马数字.md │ │ │ ├── 13. 罗马数字转整数.md │ │ │ ├── 14. 最长公共前缀.md │ │ │ ├── 151. 翻转字符串里的单词.md │ │ │ ├── 242. 有效的字母异位词.md │ │ │ ├── 28. 实现 strStr().md │ │ │ ├── 3. 无重复字符的最长子串.md │ │ │ ├── 383. 赎金信.md │ │ │ ├── 394. 字符串解码.md │ │ │ ├── 459. 重复的子字符串.md │ │ │ ├── 49. 字母异位词分组.md │ │ │ ├── 5. 最长回文子串.md │ │ │ ├── 541. 反转字符串 II.md │ │ │ ├── 6. Z 字型变换.md │ │ │ ├── 76. 最小覆盖子串.md │ │ │ ├── 8. 字符串转换整数.md │ │ │ ├── 剑指 Offer 05. 替换空格.md │ │ │ ├── 剑指 Offer 50. 第一个只出现一次的字符.md │ │ │ ├── 剑指 Offer 58 - I. 翻转单词顺序.md │ │ │ └── 剑指 Offer 58 - II. 左旋转字符串.md │ │ ├── tree │ │ │ ├── 108. 将有序数组转换为二叉搜索树 │ │ │ ├── 114. 二叉树展开为链表.md │ │ │ ├── 208. 实现 Trie (前缀树).md │ │ │ ├── 226. 翻转二叉树.md │ │ │ ├── 623. 在二叉树中增加一行.md │ │ │ ├── 98. 验证二叉搜索树.md │ │ │ ├── 剑指 Offer 07. 重建二叉树.md │ │ │ ├── 剑指 Offer 26. 树的子结构.md │ │ │ ├── 剑指 Offer 27. 二叉树的镜像.md │ │ │ ├── 剑指 Offer 28. 对称的二叉树.md │ │ │ ├── 剑指 Offer 32 - II. 从上到下打印二叉树 II.md │ │ │ ├── 剑指 Offer 32 - III. 从上到下打印二叉树 III.md │ │ │ ├── 剑指 Offer 33. 二叉搜索树的后序遍历序列.md │ │ │ ├── 剑指 Offer 55 - II. 平衡二叉树.md │ │ │ ├── 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先.md │ │ │ ├── 剑指 Offer 68 - II. 二叉树的最近公共祖先.md │ │ │ └── 剑指 Offer32 - I. 从上到下打印二叉树.md │ │ └── 技巧.md │ └── 工具 │ │ ├── Github Actions.md │ │ ├── LaTeX 数学公式.md │ │ ├── Tmux.md │ │ ├── Untitled.loom │ │ ├── Vim.md │ │ ├── mermaid.md │ │ ├── nginx.md │ │ ├── protobuf.md │ │ ├── wrk.md │ │ ├── 容器 │ │ ├── Docker.md │ │ ├── containerd.md │ │ └── k8s.md │ │ ├── 消息队列 │ │ ├── RabbitMQ.md │ │ └── kafka.md │ │ ├── 版本管理 │ │ ├── Git.md │ │ ├── gerrit.md │ │ └── svn.md │ │ └── 腾讯云云函数 SCF.md │ ├── 博物 │ ├── GeoGuessr 与图寻 │ │ ├── GeoGuessr 与图寻.md │ │ ├── 具体国家 │ │ │ ├── 意大利.md │ │ │ ├── 波兰.md │ │ │ ├── 泰国.md │ │ │ └── 西班牙.md │ │ ├── 常用的小技巧.md │ │ ├── 指示牌.md │ │ ├── 电线杆.md │ │ ├── 语言.md │ │ ├── 车牌.md │ │ └── 道路标线.md │ ├── midjourney.md │ ├── 中世纪.md │ ├── 书籍装订方法.md │ └── 双拼.md │ └── 音乐 │ ├── Blues Guitar.md │ ├── Funk Guitar.md │ ├── Jazz Guitar.md │ ├── 一些和弦进行.md │ ├── 一些好乐句.md │ ├── 五线谱.md │ ├── 从零开始推导乐理.md │ ├── 吉他指板上的乐理.md │ ├── 和弦套路.md │ ├── 教程链接.md │ ├── 通用乐理.md │ └── 音频线材详解.md ├── push.sh └── resources └── _gen └── assets └── scss ├── css ├── style.scss_d75fd08668b4bae707167bbce4d8ca46.content └── style.scss_d75fd08668b4bae707167bbce4d8ca46.json └── notes ├── book.scss_50fc8c04e12a2f59027287995557ceff.content ├── book.scss_50fc8c04e12a2f59027287995557ceff.json ├── css ├── style.scss_d75fd08668b4bae707167bbce4d8ca46.content └── style.scss_d75fd08668b4bae707167bbce4d8ca46.json └── posts └── css ├── style.scss_d75fd08668b4bae707167bbce4d8ca46.content └── style.scss_d75fd08668b4bae707167bbce4d8ca46.json /.gitignore: -------------------------------------------------------------------------------- 1 | content/posts/mystery/* 2 | .history 3 | cache.md 4 | test.md -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "themes/LoveIt"] 2 | path = themes/LoveIt 3 | url = https://github.com/dillonzq/LoveIt.git 4 | [submodule "themes/hugo-book"] 5 | path = themes/hugo-book 6 | url = https://github.com/alex-shpak/hugo-book 7 | [submodule "themes/FixIt"] 8 | path = themes/FixIt 9 | url = https://github.com/hugo-fixit/FixIt.git 10 | -------------------------------------------------------------------------------- /.hugo_build.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/.hugo_build.lock -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "svn.ignoreMissingSvnWarning": true, 3 | "workbench.colorCustomizations": { 4 | "activityBar.background": "#213308", 5 | "titleBar.activeBackground": "#2E470B", 6 | "titleBar.activeForeground": "#F7FCEF" 7 | } 8 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 摸鱼铁证 2 | 3 | 4 | 5 | 👉在线笔记 6 | 7 | 🍑GitHub主页 8 | -------------------------------------------------------------------------------- /archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /content/posts/Games/Pokemmo/搬道馆.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "pokemmo - 搬道馆" 3 | date: 2022-08-28 4 | author: MelonCholi 5 | draft: false 6 | tags: [Game] 7 | categories: [其他] 8 | date created: 24-04-10 09:59 9 | date modified: 24-04-18 14:31 10 | --- 11 | 12 | # 搬道馆 13 | 14 | ## 吹寄飞行 15 | 16 | 首发:大鸟 + 波克 17 | 18 | - 波克死了换鳄鱼,就疯狂岩崩 19 | 20 | ## 飞云虫 21 | 22 | 首发:火 + 水 23 | 24 | 平推 25 | 26 | ## 三曜 27 | 28 | ### 火 29 | 30 | 首发:鳄鱼 + 大鸟 31 | 32 | 地震 + 巨声 33 | 34 | ### 草 35 | 36 | 首发:大鸟 + 火 37 | 38 | 喷火就完事儿了 39 | 40 | ### 水 41 | 42 | 首发:鳄鱼 + 波克 43 | 44 | - 第一回合:流氓鳄切煤炭龟,波克基斯诡计 45 | - 第二回合:煤炭龟切回流氓鳄,波克基斯巨声 46 | - 之后,流氓鳄和波克基斯**地震 + 巨声**推 47 | 48 | ## 雷文电 49 | 50 | 首发:火 + 水 51 | 52 | - 如果首发电龙 + 美纳斯,火暴兽切波克基斯,水箭龟切流氓鳄,然后推 53 | 54 | ## 雪花冰 55 | 56 | 首发:龟 + 火 57 | 58 | - 煤炭龟第一回合撒隐形岩(或者切别的精灵打气势披带),火暴兽喷火 59 | 60 | ## 七宝普通 61 | 62 | 首发:鳄鱼 + 大鸟 63 | 64 | - 地震 + 岩崩 65 | - 合众一般系首发卡比兽,岩崩 + 地震可能打不死(看随机数),稳一点是鳄鱼守住一回合,大鸟岩崩一次保证能杀,因为卡比兽会臂锤流氓鳄 66 | 67 | ## 帆巴地面 68 | 69 | 首发:鳄鱼 + 波克 70 | 71 | - 地震 + 巨声,死了就换水箭龟 72 | - 波克基斯首发是为了对付土台龟、蟾蜍王。 73 | - 如果对面有沙暴 + 龙头地鼠或穿山王(拨沙特性),必须切煤炭龟顶掉天气 74 | 75 | ## 双龙龙 76 | 77 | 首发:鳄鱼 + 波克 78 | 79 | - 鳄鱼守住 + 波克诡计 80 | - 如果对面首发波士可多拉,那先鳄鱼秒掉 81 | -------------------------------------------------------------------------------- /content/posts/Games/Pokemmo/果农.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "pokemmo - 果农" 3 | date: 2022-08-28 4 | author: MelonCholi 5 | draft: true 6 | tags: [Game] 7 | categories: [其他] 8 | --- 9 | 10 | # 果农 11 | 12 | ## PP 果 13 | 14 | 原料 15 | 16 | - 微甜 1000 17 | 18 | - 微苦 1100 19 | - 超辣 1900 20 | 21 | 利润 22 | 23 | - 一颗 pp 种子成本 4000 24 | - pp 果 900,收获 5 到 7 个,售价 4500 到 6300 25 | 26 | - 利润 500 到 2300 27 | 28 | > 卖一组,9900 手续费 29 | 30 | 土地 31 | 32 | - 吹寄,可种 72 棵 -------------------------------------------------------------------------------- /content/posts/Games/Super auto pets/一些流派.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/content/posts/Games/Super auto pets/一些流派.md -------------------------------------------------------------------------------- /content/posts/Games/ptcg/简中单卡分析/泽.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/content/posts/Games/ptcg/简中单卡分析/泽.md -------------------------------------------------------------------------------- /content/posts/Games/ptcg/简中单卡分析/苍.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/content/posts/Games/ptcg/简中单卡分析/苍.md -------------------------------------------------------------------------------- /content/posts/Games/ptcg/简中单卡分析/赫.md: -------------------------------------------------------------------------------- 1 | # 赫 2 | 3 | ## 喷火龙 4 | 5 | - 一般,填能太慢 6 | 7 | - 不过贵 8 | 9 | image-20221105155724339 10 | 11 | ## 熔岩蜗牛 12 | 13 | 14 | 15 | image-20221105155707559 16 | -------------------------------------------------------------------------------- /content/posts/Games/ptcg/繁中卡表.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "卡表" 3 | date: 2022-09-01 4 | author: MelonCholi 5 | draft: false 6 | tags: [Game] 7 | categories: [其他] 8 | --- 9 | 10 | # 卡表 11 | 12 | 冰水龙 https://ptcgtw.shop/?s=RA8235(日本上位) 13 | 14 | 鬼龙 15 | 16 | - https://ptcgtw.shop/?s=HN6145(大青菜) 17 | - https://ptcgtw.shop/?s=TB8610(日本上位) 18 | 19 | 迷失黏美龙 https://ptcgtw.shop/?s=FH8358(日本上位) 20 | 21 | 索罗亚克 22 | 23 | - https://ptcgtw.shop/?s=MR1904(日本上位)带 4 超级球 24 | - https://ptcgtw.shop/?s=WX6811(日本上位2)带老大、蒂安希 25 | - https://ptcgtw.shop/?s=LN5274(废柴猫上位)带大护符、土龙 26 | 27 | 达克莱伊 28 | 29 | - https://ptcgtw.shop/?s=WK8202(日本上位)带老大 30 | - https://ptcgtw.shop/?s=MS6706 (日本上位 2)带风王 -------------------------------------------------------------------------------- /content/posts/Games/世界弹射物语/abs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "世界弹射物语 abs" 3 | date: 2023-03-29 4 | author: MelonCholi 5 | draft: false 6 | tags: [Game] 7 | categories: [其他] 8 | --- 9 | 10 | # abs 11 | 12 | ## 里脊 13 | 14 | ![image-20230329205936205](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329205936205.png) 15 | 16 | ![image-20230329222416399](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329222416399.png) 17 | 18 | ## 好用的新角色 19 | 20 | ### 顿足奶 21 | 22 | ![image-20230329215249245](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329215249245.png) 23 | 24 | ### 皮亚莫 25 | 26 | ![image-20230329215736075](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329215736075.png) 27 | 28 | ## 礼铳 29 | 30 | ![image-20230329221024120](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329221024120.png) 31 | 32 | 金木、烟奶不可替代 33 | 34 | 太母也很重要 35 | 36 | ## lcw 37 | 38 | ![image-20230329221533585](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329221533585.png) 39 | 40 | ## 光弹拴狗 41 | 42 | ![image-20230329221800304](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329221800304.png) 43 | 44 | ## 圣女拴狗 45 | 46 | ![image-20230329222141330](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329222141330.png) 47 | 48 | ## 拴狗风 49 | 50 | ![image-20230329222222074](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329222222074.png) 51 | 52 | ## 宇宙 pf 53 | 54 | 队长位一定要是拳 pf 55 | 56 | ![image-20230329222508823](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230329222508823.png) -------------------------------------------------------------------------------- /content/posts/Games/围棋/基础知识.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 基础知识 -------------------------------------------------------------------------------- /content/posts/Games/文明六/德国.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "文明六 - 德国" 3 | date: 2022-11-13 4 | author: MelonCholi 5 | draft: false 6 | tags: [Game] 7 | categories: [其他] 8 | --- 9 | 10 | # 德国 11 | 12 | ![image-20221113191620781](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113191620781.png) 13 | 14 | 开局 15 | 16 | - 两猴 - 两开拓 / 一开拓一工人 17 | 18 | 注意 19 | 20 | - 挨着造城 21 | - 万神选宗教移民 22 | 23 | ![image-20221113190954580](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113190954580.png) 24 | 25 | ## 规划 26 | 27 | ![](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113225542890.png) 28 | 29 | ![image-20221113191813014](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113191813014.png) -------------------------------------------------------------------------------- /content/posts/Games/文明六/拜占庭.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "文明六 - 拜占庭" 3 | date: 2022-11-13 4 | author: MelonCholi 5 | draft: false 6 | tags: [Game] 7 | categories: [其他] 8 | --- 9 | 10 | # 拜占庭 11 | 12 | ![image-20221113152455283](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113152455283.png) 13 | 14 | ![image-20221113142036684](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142036684.png) 15 | 16 | ![image-20221113142042792](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142042792.png) 17 | 18 | ![image-20221113142047632](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142047632.png) 19 | 20 | ![image-20221113142052039](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142052039.png) 21 | 22 | ![image-20221113142056556](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142056556.png) 23 | 24 | ![image-20221113142103163](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142103163.png) 25 | 26 | ![image-20221113142108434](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20221113142108434.png) -------------------------------------------------------------------------------- /content/posts/poetry/classical.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "诗" 3 | date: 2021-10-23 4 | author: MelonCholi 5 | draft: false 6 | tags: [古体诗] 7 | categories: [其他] 8 | --- 9 | 10 | # 诗 11 | 12 | 长安紫陌芙蓉阙 13 | 14 | 马嵬坡下白练雪 15 | 16 | 何必长存破风意 17 | 18 | 红尘万丈早归去 19 | 20 | ​ (HWSN 2017.6.19) 21 | 22 | 23 | 24 | 忆江南 25 | 26 | 梅时雨,舟桨渡平川 27 | 28 | 烟卷云浓西去水,风斜雾横北归山 29 | 30 | 犹把露衣沾 31 | 32 | ​ (2017.7.9) 33 | 34 | 35 | 36 | 不屑牛酒寻上色 37 | 38 | 嘲凡皮相美天功 39 | 40 | ​ (2017.10.25) 41 | 42 | 43 | 44 | 巧巧红妆花间客,朵朵轻云芳柔甚 45 | 46 | 片月风流夜搅衣,风雨归去空留恨 47 | 48 | 愿莫效此薄情郎,伤心万尺倾国色 49 | 50 | 51 | 52 | 少小臣嗣玉金环,暇时万把腰千缠 53 | 54 | 缠得非金却何是?罗红绮蓝葱头簪 55 | 56 | 碧眼丹容含春意,多情自小现端倪 57 | 58 | 不喜舞剑喜柳面,不爱经籍爱芳仪 59 | 60 | 锦缎丝袍穿巷井,璎珞摇鸣逐娇影 61 | 62 | 借齿伶俐讨巧笑,凭笔生花画蛾螓 63 | 64 | 拥衾兰语如梦令,阁床狂酒醉花阴 65 | 66 | 好晴悠游江城子,云黑卧看雨霖铃 67 | 68 | 69 | 70 | 暗潮波生惊沉帆,家世蒙蔑翻宦海 71 | 72 | 诛雷疾发荒四壁,华尘梦烟皆飞散 73 | 74 | 从此落魄贵公子,白马孤魂踏九川 75 | 76 | 77 | 78 | 五陵金枝桃李年,眉若远黛肤胜雪 79 | 80 | 紫陌逢识少年后,自此未语不成眠 81 | 82 | 一纸鱼信悄相约,风萍飘乎长安月 83 | 84 | 芙蓉帐里情悠悠,鸳鸯枕头语窃窃 85 | 86 | 红烛冷褪马前归,喃口两语赠长别 87 | 88 | “他年两情离魂所,明朝花红柳河纤” 89 | -------------------------------------------------------------------------------- /content/posts/poetry/modern.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "诗" 3 | date: 2021-10-23 4 | author: MelonCholi 5 | draft: false 6 | tags: [现代诗] 7 | categories: [其他] 8 | --- 9 | 10 | # 诗 11 | 12 | 听惯莫名来的雨 13 | 14 | 只道又不知是谁的眼泪 15 | 16 | 轻轻落在夜的脚边 17 | 18 | ​ (Ls 2019.4.14) 19 | 20 | 21 | 22 | “谁不爱懦弱的快活?” 23 | 24 | 小草们临风呼叫 25 | 26 | “我织上泥土的颜色,泥土编织成我 27 | 28 | 风来,我就起到天际” 29 | 30 | 风止了你才肯罢休 31 | 32 | 33 | 34 | 可总有人要骑上野马 35 | 36 | 去踏碎满地的骄傲 37 | 38 | (Sty 2019.3.12) 39 | 40 | 41 | 42 | 何必掘出春天的墓骨 43 | 44 | 迫她目睹她梦的毁灭 45 | 46 | 丑恶断不能无人欣赏 47 | 48 | 那就让美来歌颂卑劣 49 | 50 | ​ (Sty 2019.1.21) 51 | 52 | 53 | 54 | # 55 | -------------------------------------------------------------------------------- /content/posts/poetry/谷歌的诗/巧巧红妆花间客.md: -------------------------------------------------------------------------------- 1 | 巧巧红妆花间客,朵朵轻云芳柔甚 2 | 3 | 片月风流夜搅衣,风雨归去空留恨 4 | 5 | 愿莫效此薄情郎,伤心万尺倾国色 6 | 7 | 少小臣嗣玉金环,暇时万把腰千缠 8 | 9 | 缠得非金却何是?罗红绮蓝葱头簪 10 | 11 | 碧眼丹容含春意,多情自小现端倪 12 | 13 | 不喜舞剑喜柳面,不爱经籍爱芳仪 14 | 15 | 锦缎丝袍穿巷井,璎珞摇鸣逐娇影 16 | 17 | 借齿伶俐讨巧笑,凭笔生花画蛾螓 18 | 19 | 拥衾兰语如梦令,阁床狂酒醉花阴 20 | 21 | 好晴悠游江城子,云黑卧看雨霖铃 22 | 23 | 24 | 25 | Ver1 26 | 27 | 聪明的红花化妆盛开的软云 28 | 29 | 浪漫的月夜摇摆着衣裳,风雨归来,恨意在身后。 30 | 31 | 我希望你充满悲伤,不要模仿这个瘦弱的情人 32 | 33 | 年轻大臣继承金戒指 34 | 35 | 但它是什么?罗红旗葱花簪 36 | 37 | 蓝眼睛的子弹代表春天,感伤的线索来自童年。 38 | 39 | 不喜欢剑舞柳面,不喜欢经书爱芳仪 40 | 41 | 锦织的丝袍穿过小巷,璎珞尖叫着追着那人影。 42 | 43 | 用你的牙齿微笑,用笔画花和飞蛾。 44 | 45 | 被窝里的对话如梦,床醉醉醺醺 46 | 47 | 玉江城子好,云淡风轻,可以看到玉林岭 48 | 49 | 50 | 51 | Ver2 52 | 53 | 花儿很美,有红饰,有明云,有云彩 54 | 55 | 夜里,风、光波和他的衣服跟着风雨增加 56 | 57 | 希望不要跟着瘦子的理想走 58 | 59 | 60 | 61 | 年轻的牧师找到了金戒指。 62 | 63 | 但这罗那古青葱发烫到底是什么东西? 64 | 65 | 蓝色沙漏看起来像春天他年轻时就表现出愤怒 66 | 67 | 我不喜欢跳舞,但阿富汗书里的婚姻 68 | 69 | 英拉的车掉进了阴影里。 70 | 71 | 用你美丽的微笑牙齿,把它们放在花或月亮铅笔上 72 | 73 | 有失眠、失眠、酗酒等作用 74 | 75 | 安昌昌喜欢在乌云中陪他走 76 | 77 | 78 | 79 | 她的行为激怒了辛哈,羞辱了她的家人,使她成为了一个好领导 80 | 81 | 病毒蔓延到了胡成的梦墙,所有的烟雾都消失了。 82 | 83 | 最近,由强大的约翰王带领的精神开始了 84 | 85 | 86 | 87 | 好没有坏马保险 88 | 89 | 然而,即墨遇到一个年轻人就睡不着觉 90 | 91 | 纸鱼缓慢移动,查纳的风不像月亮 92 | 93 | 学校的乐趣,老鼠的乐趣,问和冲刺的练习 94 | 95 | 回家前症状略有缓解 96 | 97 | “他把妻子留在家里,爱上了她两年。当时,敏明住在一个红色的六角形区域。” -------------------------------------------------------------------------------- /content/posts/useful/Go dockerfile 通用配置.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Go Dockerfile 通用配置" 3 | date: 2022-06-25 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [有用的东东] 8 | aliases: [Go Dockerfile 通用配置] 9 | date created: 24-04-10 09:58 10 | date modified: 24-04-25 18:39 11 | --- 12 | 13 | # Go Dockerfile 通用配置 14 | 15 | ```dockerfile 16 | FROM golang:alpine AS builder 17 | RUN apk add --no-cache git 18 | 19 | ENV GO111MODULE=on \ 20 | CGO_ENABLED=0 \ 21 | GOOS=linux \ 22 | GOARCH=amd64 \ 23 | GOPROXY=https://goproxy.cn \ # 使用国内镜像源,如果要在actions里跑的话就不用 24 | GOPRIVATE=github.com/ # 私有组织 25 | 26 | WORKDIR /build 27 | 28 | COPY . . 29 | 30 | # 如果要go get私人仓库 31 | RUN git config \ 32 | --global \ 33 | url."https://:@github.com".insteadOf \ 34 | "https://github.com" 35 | RUN go get github.com// 36 | 37 | 38 | # 编译成二进制可执行文件server 39 | RUN go build -o server . 40 | 41 | # 创建小镜像 42 | FROM scratch 43 | 44 | 45 | # 拷贝配置文件 46 | COPY ./configs/server.yml / 47 | # 从builder镜像中把/build/server 拷贝到当前目录 48 | COPY --from=builder /build/server / 49 | 50 | # 声明服务端口 51 | EXPOSE 8080 52 | 53 | # 启动容器时运行的命令 54 | CMD ["/server", "--config", "/server.yml"] 55 | ``` 56 | -------------------------------------------------------------------------------- /content/posts/useful/useful.md: -------------------------------------------------------------------------------- 1 | --- 2 | obsidianUIMode: preview 3 | --- 4 | # useful Overview 5 | 6 | ```ccard 7 | type: folder_brief_live 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /content/posts/useful/配置 VSCode.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "配置 VSCode" 3 | date: 2023-02-21 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [有用的东东] 8 | --- 9 | 10 | # 配置 VSCode 11 | 12 | > https://geek-docs.com/vscode/vscode-tutorials/what-is-vscode.html 13 | 14 | ## Debug 按键解释 15 | 16 | - **继续** F5:直接跳到下一个断点 17 | - **逐过程** F10:运行到**当前文件夹**的下一行(跳过当前语句,调用其他文件夹的所有语句) 18 | - 比如 a = func_b(),如果 func_b 是其他文件夹定义的复杂函数,直接跳过; 19 | - **单步调试** F11:运行到自己写的文件下一行语句(最细致) 20 | - 比如 a = func_b(),如果 func_b 是其他文件定义的复杂函数,则进入其他文件,运行下一步; 21 | - **单步跳出** Shift + F11:当 debug 陷入某个循环时,直接跳过当前循环。 22 | - **重启**,重新 debug 23 | 24 | ## 常用快捷键记录 25 | 26 | ### 全局配置 27 | 28 | pin:Ctrl + Alt + P 29 | 30 | 搜索文件:Ctrl + P 31 | 32 | ### 插件配置 33 | 34 | 添加书签:Ctrl + Alt + M 35 | 36 | 复制行所在的文件路径及行号:Alt + L 37 | 38 | ### 个人配置 39 | 40 | 前进,后退:Alt + ←,Alt + → 41 | -------------------------------------------------------------------------------- /content/posts/useful/配置 Visual Studio.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "配置 visual studio" 3 | date: 2022-03-25 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [有用的东东] 8 | --- 9 | 10 | # 配置 Visual Studio 11 | 12 | ## 美化 13 | 14 | ### 主题 15 | 16 | One Dark Pro 17 | 18 | ### 代码配色优化 19 | 20 | 配色参考 21 | 22 | - http://www.360doc.com/content/13/1023/17/1427138_323568638.shtml 23 | 24 | - http://www.360doc.com/content/14/0730/07/12530471_398042223.shtml 25 | 26 | #### 注释 27 | 28 | (85, 107, 80) 29 | 30 | ![image-20210822223502440](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20210822223502440.png) 31 | 32 | (127, 132, 142) 33 | 34 | ![image-20210822223524260](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20210822223524260.png) 35 | 36 | #### 变量(标识符) 37 | 38 | (200, 200, 169) 39 | 40 | ![image-20210822223559945](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20210822223559945.png) 41 | 42 | (178, 200, 187) 43 | 44 | ![image-20210822223616672](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20210822223616672.png) -------------------------------------------------------------------------------- /content/posts/useful/配置 gitbook.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "配置 Gitbook" 3 | date: 2022-04-25 4 | draft: true 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [有用的东东] 8 | --- 9 | 10 | # 配置 Gitbook 11 | 12 | ## 插件 13 | 14 | theme-comscore:颜色主题 15 | 16 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/DataBase/ex4.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 实验四 6 | 7 | ​ 孙天野 19120198 8 | 9 | 对 school 数据库做如下操作: 10 | 11 | 1. **建立计算机学院总评不及格成绩学生的视图,包括学生学号、姓名、性别、手机、所选课程和成绩** 12 | 13 | ```sql 14 | CREATE VIEW view1 ( xh, xm, xb, sjhm, km, zpcj ) AS ( 15 | SELECT 16 | e.xh, 17 | xm, 18 | xb, 19 | sjhm, 20 | km, 21 | zpcj 22 | FROM 23 | e 24 | INNER JOIN s ON e.xh = s.xh 25 | INNER JOIN c ON e.kh = c.kh 26 | WHERE 27 | e.zpcj < 60 28 | AND s.yxh = 1) 29 | ``` 30 | 31 | ![image-20211223134705794](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211223134705794.png) 32 | 33 | 2. **求年龄大于所有女同学年龄的男学生姓名和年龄** 34 | 35 | ```sql 36 | SELECT 37 | xm, 38 | 2021-year ( s.csrq ) AS age 39 | FROM 40 | s 41 | WHERE 42 | s.xb = "男" 43 | AND s.csrq <( 44 | SELECT 45 | min( s.csrq ) 46 | FROM 47 | s 48 | WHERE 49 | s.xb = "女") 50 | ``` 51 | 52 | ![image-20211223134734056](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211223134734056.png) 53 | 54 | 3. **在 E 表中修改 08305001 课程的平时成绩,若成绩小于等于 75 分时提高 5%,若成绩大于 75 分时提高 4%** 55 | 56 | ```sql 57 | UPDATE e SET pscj = pscj * 1.05 WHERE pscj <= 75; 58 | UPDATE e SET pscj = pscj * 1.04 WHERE pscj > 75; 59 | ``` 60 | 61 | 4. **删除没有开课的学院** 62 | 63 | ```sql 64 | DELETE 65 | FROM 66 | d 67 | WHERE 68 | NOT EXISTS ( 69 | SELECT 70 | * 71 | FROM 72 | o 73 | INNER JOIN c ON o.kh = c.kh 74 | WHERE 75 | c.yxh = d.yxh 76 | ) 77 | ``` 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/安保/ex4.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 实验四 6 | 7 | https://zhuanlan.zhihu.com/p/48249182 8 | 9 | **推导 rsa 私钥** 10 | 11 | 随机选择两个不相等的质数 p 和 q 12 | 13 | 计算 p 和 q 的乘积 n 14 | 15 | 计算 n 的欧拉函数 φ(n) = (p-1)(q-1) 16 | 17 | 随机选择一个整数 e,满足 1< e < φ(n),且 e 与 φ(n) 互质 18 | 19 | 计算 e 对于 φ(n) 的模反元素 d 20 | 21 | 即 ed ≡ 1 (mod φ(n)) 22 | 23 | 等价于 ed - 1 = kφ(n) 24 | 25 | 将 n 和 e 封装成公钥,n 和 d 封装成私钥 26 | 27 | 28 | 29 | 公钥加密算法 30 | 31 | 设加密信息 m,其必须是整数(字符串可以取 ascii 值或 unicode 值),且 m > n。 32 | 33 | 求出对应的密文 c: 34 | 35 | **m^e^ ≡ c (mod n)** 36 | 37 | 38 | 39 | 私钥解密算法 40 | 41 | **c^d^ ≡ m (mod n)** 42 | 43 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/数字图像处理/homework/Chapter4.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 第四章 6 | 7 | ![image-20211020180137663](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211020180137663.png) 8 | 9 | 不会有区别。因为无论哪种填充方式,都能同样地分离图像 10 | 11 | **** 12 | 13 | ![image-20211020181106974](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211020181106974.png) 14 | 15 | 上述的操作中,“取该变换的复共轭” 一步,将傅里叶变换中的 j 改为了 -j,从而将原图函数 f(x, y) 转换为 f(-x, -y),造成图像的镜面翻转 16 | 17 | ![image-20211020181131232](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211020181131232.png) 18 | 19 | **** 20 | 21 | ![image-20211020181641145](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211020181641145.png) 22 | 23 | 1. 如果只进行了高通操作,戒指会有一个黑暗的中心。但是这个黑暗的中心区域被低通滤波器平均化了。 24 | 25 | 戒指中心明亮的原因是,环状物边界上的不连续边缘比图像中其他地方高得多 26 | 27 | 2. 不会,因为傅里叶变换进行滤波是一个线性过程。 28 | 29 | **** 30 | 31 | ![image-20211024122318023](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211024122318023.png) 32 | 33 | ![image-20211024122327840](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211024122327840.png) 34 | 35 | (a) 是的,图像不会发生变化。存在一个 K 值,使图像中所有像素灰度值的平均值为 0。 36 | 37 | (b) ![image-20211024122745572](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211024122745572.png) 38 | 39 | **** 40 | 41 | ![image-20211024122920032](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211024122920032.png) 42 | 43 | 1. 中值滤波以消除孤立亮点 44 | 45 | 2. 高通滤波以增强对比度 46 | 47 | 3. 直方图均衡 48 | 49 | 4. 计算平均灰度为 V~0~,再对于所有像素加上 (V-V~0~) 灰度 50 | 51 | 5. 对所有像素执行以下函数: 52 | 53 | image-20211024123325702 54 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/数字图像处理/homework/Chapter8.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 第八章 6 | 7 | ![image-20211031163705599](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211031163705599.png) 8 | 9 | (a) 直方图均衡过后,每个灰度级概率趋于相等,使用变长编码毫无优势。 10 | 11 | (b) 直方图均衡后,像素点之间仍然存在空间相关性,所以有空间冗余;同时也允许包含时间冗余。 12 | 13 | **** 14 | 15 | ![image-20211031171349148](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211031171349148.png) 16 | 17 | (a) $C=\frac{8}{5.3}=1.509$ 18 | 19 | (b) 不能 20 | 21 | (c) 在哈夫曼编码之前消除图像中的空间冗余 22 | 23 | **** 24 | 25 | ![image-20211031171950452](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211031171950452.png) 26 | 27 | a3a6a6a2a5a2a2a2a4 28 | 29 | **** 30 | 31 | ![image-20211031164716841](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211031164716841.png) 32 | 33 | 1.544 Mbps 的传输率在 6s 内可以传输 34 | $$ 35 | (1.544\times 10^6)\times 6=9.264\times 10^6 36 | $$ 37 | 比特信息,所以可得压缩比为 38 | $$ 39 | C=\frac{4096\times 4096\times 12}{9.264\times 10^6}=21.73 40 | $$ 41 | JPEG 变换编码可以实现此压缩。 42 | 43 | 要在 5-6s 内做一次细化,1min 内完成,相当于要做 10-12 次细化。不妨假设做 12 次细化,每次细化针对 12bit 其一,那每个比特的压缩率为 44 | $$ 45 | C=\frac{4096\times 4096\times 1}{9.264\times 10^6}=1.81 46 | $$ 47 | 压缩比必须小于 2。 48 | 49 | 为了体验每幅图像之间的差异,可以在压缩图像每个像素每个比特位置与原始图像进行异或操作,值为 1 则代表此比特位置与原始值不同。 50 | 51 | ![image-20211031171056431](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20211031171056431.png) -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/编译原理/Chapter1.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 作业一 编译概述 6 | 7 | 19120198 孙天野 8 | 9 | 1. **解释下列术语** 10 | 11 | 1. 编译程序:把用高级程序设计语言书写的源程序,翻译成等价的机器语言格式目标程序的翻译程序 12 | 2. 源程序:使用源语言编写的程序 13 | 3. 目标程序:是源程序经编译可直接被计算机运行的机器码集合,在计算机文件上以 .obj 作扩展名。 14 | 4. 前端:主要依赖于源语言而与目标机无关,包括词法分析、语法分析、语义分析、中间代码生成这些阶段,以及相关的出错处理工作、符号表管理工作 15 | 5. 后端:依赖于目标机而一般不依赖于源语言,只与中间代码有关的工作,包括目标代码生成,及其相关的出错处理工作、符号表管理工作 16 | 6. 遍:一个编译过程可由一遍、两遍、或多遍完成。 17 | 18 | 2. **编译程序的主要构成成分,及其主要功能:** 19 | 20 | - **词法分析**:从左到右一个字符一个字符地读入源程序,对构成源程序的字符流进行扫描和分解,从而识别出一个个符号 21 | - **语法分析**:在词法分析的基础上将单词序列分解成各类语法短语。 22 | - **语义分析**:审查源程序有误语义错误,为代码生成阶段搜集类型信息。 23 | - **中间代码生成**:一种结构简单、含义明确的记号系统。 24 | - **代码优化**:对前一阶段产生的中间代码进行变换或进行改造,使生成的目标代码更为高效,即省时间和省空间。 25 | - **目标代码生成**:把中间打吗变换成特定机器上的绝对值零代码或可重定位的指令代码或汇编指令代码。 26 | - **表格管理程序**:记录源程序中使用的名字,收集每个名字的各种属性信息,如类型、作用域、分配存储信息。 27 | - **出错处理程序**:检查错误、报告出错信息、排错、恢复编译工作。 28 | 29 | 3. **什么是解释程序?它与编译程序的主要不同是什么?** 30 | 31 | 解释程序接受某个语言的程序并立即运行这个源程序。 32 | 33 | 它与编译程序的区别: 34 | 35 | - 对于编译程序,它把高级语言程序翻译成某个机器的汇编语言程序或二进制代码程序,这个二进制代码程序在机器上运行以生成结果。编译和运行的、是两个独立分开的阶段。 36 | - 对于解释程序,它不需要在运行前先把源程序翻译成目标程序,也可以实现在某台机器上运行程序并生成结果。 -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/编译原理/Chapter2.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 作业二 文法与语言 6 | 7 | 19120198 孙天野 8 | 9 | 1. ![image-20220404150016571](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220404150016571.png) 10 | 11 | 全部元素:{abc} 12 | 13 | 2. ![image-20220404150358755](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220404150358755.png) 14 | 15 | 全体非负整数 16 | 17 | 10. ![image-20220404150535456](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220404150535456.png) 18 | 19 | $$ 20 | G(E)=E=E+T=E+T*F 21 | $$ 22 | 23 | 故 $E+T*F$ 是它的一个右句型 24 | 25 | - 短语:$E+T*F$ 26 | - 直接短语:$T*F$ 27 | - 句柄:$T*F$ 28 | 29 | 15. ![image-20220404151110796](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220404151110796.png) 30 | 31 | 允许 0 打头 32 | $$ 33 | \begin{flalign} 34 | &\ G(S) \\ 35 | &\ S \rightarrow C|AC \\ 36 | &\ C \rightarrow B|AB \\ 37 | &\ A \rightarrow 0|1|2|3|4|5|6|7|8|9 \\ 38 | &\ B \rightarrow 0|2|4|6|8 39 | \end{flalign} 40 | $$ 41 | 不允许 0 打头 42 | $$ 43 | \begin{flalign} 44 | &\ G(S) \\ 45 | &\ S \rightarrow 0|C|AC \\ 46 | &\ C \rightarrow B|AB \\ 47 | &\ A \rightarrow 1|2|3|4|5|6|7|8|9 \\ 48 | &\ B \rightarrow 2|4|6|8 49 | \end{flalign} 50 | $$ 51 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/编译原理/思路.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 思路 6 | 7 | ![image-20220310095026534](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220310095026534.png) 8 | 9 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210308143507243.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0ODUwNzI1,size_16,color_FFFFFF,t_70) -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/计算机系统结构/ex5.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 计算机系统性能评价 6 | 7 | 实验目的:用正确的方法(或工具)评估计算机系统(单机)的主要性能指标。 8 | 9 | 回答下列问题: 10 | 11 | 1. 选择计算机系统的 1 个“主要”性能指标。 12 | 13 | 2. 这个指标怎么测量?解释测量原理。 14 | 15 | 3. 选择合适的工具或自编程序测出该指标值,并作出评价。 16 | 17 | 本实验选取了 CPU 主频这个指标进行测量。 18 | 19 | CPU 的主频,即 CPU 内核工作的时钟频率(CPU Clock Frequency),它表示在 CPU 内数字脉冲信号震荡的速度。通常用由 MHz(兆赫,或者每秒百万脉冲)或者 GHz(千兆赫,每秒十亿脉冲)来表示。 20 | 21 | 计算方法:时钟频率(f)与周期(T)两者互为倒数:f=1/T 22 | 23 | 这个公式的意思是:时钟频率为时钟在 1 秒钟内重复的次数。 24 | 25 | 而目前的 CPU 普遍已经处于 GHz 级,也就是说每秒钟会产生 10 亿个脉冲信号。 26 | 27 | 一般 CPU 厂商会提供这个参数给用户参考,Windows 系统下,我们可以在任务管理器的性能栏下查看 28 | 29 | ![image-20220514152926070](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220514152926070.png) 30 | 31 | 我们还可以借助一些性能测量工具,通过运行一段示例来查看 CPU 主频的实时变化。这里我们使用了 3DMark 工具 32 | 33 | ![image-20220514153052967](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220514153052967.png) 34 | 35 | 可以看到 CPU 的主频不是一成不变的,我们再将其与实时温度曲线图做对比: 36 | 37 | ![image-20220514153259537](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220514153259537.png) 38 | 39 | 会发现当温度上升时,主频往往会降低。 40 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/计算机英语/1.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | https://dev.to/excceedd/how-to-solve-coding-issues-in-four-easy-steps-3j5g 6 | 7 | This article tells about how to solve coding problems in a four-steps way. It really helps me because problem solving is an important indicator in a job interview. 8 | 9 | Recognize the issue. Although job interview won't give you much time to think, you still need to fully understand the issue before solving. 10 | 11 | Make a strategy. Strategy is a kind of plan before coding. There are several ways to design a strategy. Pseudo-code seems a good choice for me. "consider systematically how a human solves the problem." this principle helps me a lot. 12 | 13 | Execute the plan. This is a core part of solving, the step needs you to write actual code. The author offers a useful skill: Ignore the difficult part of the problem that you don't understand for the time being and write out the other parts. 14 | 15 | Take a look back. Examining your code is a essential step. You should consider all situations, especially some border conditions. 16 | 17 | -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/计算机英语/2.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | https://dev.to/latobibor/should-we-have-test-managers-again-mkf 6 | 7 | This article argues about whether we should have test engineer. Compare to a bunch of manual testers, the author prefer a professional testing team. A test automation engineer will dedicating his/her time to what to test, how to test effectively and when to avoid writing expensive or weak test suites. This makes test unit more powerful and robust. 8 | 9 | Tested by who developed is a bad idea, according to the article. The closer testers are to the actual creator of the code, the less likely they will find a bug. And developer will not have much time to learn a series of professional testing methods. More over, they even ghosting responsibilities when it comes to multiple teams testing together. -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/计算机英语/3.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | https://dev.to/fastcodeinc/low-code-platforms-full-code-developers-a-match-made-in-hell-32ie 6 | 7 | Low-code development has been a hot trend in recent years. But it is controversial at the same time. This article mainly discuss what are the disadvantage of low-code platform. 8 | 9 | Low-code mode actually provides a visual platform to build your application, it's like a toy: strong in building little project, weak in writing a large app. And how to test it has become a bottleneck for its future. 10 | 11 | The article also tells that low-code platform will limits career mobility. Different company have different low-code solutions, it's really hard to reuse, and the traditional technical skills in open programming languages and frameworks will disappear gradually. 12 | 13 | However, a low-code platform especially built for professional developers is a better idea, it will eliminates the disadvantages of proprietary low-code platforms. -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/计算机英语/4.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | https://dev.to/anthonyjdella/why-you-should-use-a-developer-font-2gio 6 | 7 | The most important feature of a program developer is a editor that has a cool style. We look at codes all day long, so font of codes is often overlooked but vital for the coding experience. This article emphasizes the importance of code fonts. 8 | 9 | A good code font will help you find typos, variables and functions quickly. Code highlighting makes developers more efficient. 10 | 11 | Companies which design IDE usually have their own code font. For example, Jetbrains Mono. It has a higher height, makes code easier to recognize. And it has some useful ligatures to identify special characters (though I don't really like it). Each character is distinct, 1, l and I is easy to read, while they look the same with a lot of standard fonts. -------------------------------------------------------------------------------- /content/posts/专业/Archive/HomeWork/计算机英语/5.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | https://dev.to/ben/what-are-your-tips-for-an-effective-developer-resume-ep4 6 | 7 | This is not a traditional article, it's like a discussion in forums. Many developers left their wise advise in this posting. The subject is *What are your tips for an effective developer resumé*. It helps me a lot because I happen to be looking for an internship as well. Here are some suggestions that I have benefited from. 8 | 9 | Don’t list every technology you have ever done “hello world” in. Just list the knowledge and skills that you are really good at and that fit the target position. You will never be expert of every field. 10 | 11 | Make sure to link to your socials. Especially GitHub, this is the perfect platform to showcase yourself. 12 | 13 | Try and showcase how well you will perform in a team. Try to tailor the descriptions of your project experience to match the job you are applying for. -------------------------------------------------------------------------------- /content/posts/专业/Courses/离散数学/题型.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "离散数学2 题型" 3 | date: 2021-10-23 4 | draft: true 5 | author: "MelonCholi" 6 | tags: [离散数学] 7 | categories: [专业课] 8 | --- 9 | 10 | (一)题型 11 | 12 | - 不定项选择题 5 个 10 分 考定义 13 | - 下列哪些是命题? 14 | - 关系性质定义 15 | - 命题公式类型 永真、可满足... 16 | - 特殊关系 恒等、小于等于、全序... 性质 17 | - 函数 单射、满射... 18 | - 连接词的完备集 19 | - (主)析\合取范式 差别 20 | - (传递关系)表 21 | - 根据哈斯图写偏序关系 22 | - 反函数的定义,在什么情况下有反函数 23 | 24 | - 判断 5 个 10 分 25 | - 填空 5 空 10 分 26 | - 一阶逻辑的符号化 27 | - 主析\合取范式 极小\大项 28 | - 关系 定义域 值域 29 | - 等价关系的商集 30 | - 函数的合成 31 | - 4-10 大题 计算证明 32 | - 4 逻辑公式 33 | - 5 关系(重点 偏序集 哈斯图 元、界) 34 | - 6 逻辑中的应用题 35 | - 7 推理证明 36 | - 8 关系 (重点证明等价关系、偏序关系) 37 | - 9 关系 (warshall 求闭包) 38 | - 10 函数(证明单射满射) -------------------------------------------------------------------------------- /content/posts/专业/Courses/计算机视觉.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "计算机视觉" 3 | date: 2021-03-08 4 | draft: true 5 | author: "MelonCholi" 6 | tags: [计算机视觉] 7 | categories: [专业课] 8 | --- 9 | 10 | # 计算机视觉 11 | 12 | -------------------------------------------------------------------------------- /content/posts/专业/DataBase/SQLite.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "SQLite" 3 | date: 2021-10-23 4 | author: MelonCholi 5 | draft: false 6 | tags: [数据库,快速入门] 7 | categories: [数据库] 8 | --- 9 | 10 | # SQLite 11 | 12 | ## 认识 13 | 14 | SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。 15 | 16 | 就像其他数据库,SQLite 引擎不是一个独立的进程,且可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。 17 | 18 | ### 特性 19 | 20 | - 不需要一个单独的服务器进程或操作的系统(无服务器的)。 21 | - 不需要配置,这意味着不需要安装或管理。 22 | - 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。 23 | - SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于 250KiB。 24 | - SQLite 是自给自足的,这意味着不需要任何外部的依赖。 25 | - SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。 26 | - SQLite 支持 SQL92(SQL2)标准的大多数查询语言的功能。 27 | - SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的 API。 28 | - SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运行。 29 | 30 | ### 命令 31 | 32 | 与关系数据库进行交互的标准 SQLite 命令类似于 SQL。命令包括 CREATE、SELECT、INSERT、UPDATE、DELETE 和 DROP。这些命令基于它们的操作性质可分为以下几种: 33 | 34 | **DDL - 数据定义语言** 35 | 36 | | 命令 | 描述 | 37 | | :----- | :----------------------------------------------------- | 38 | | CREATE | 创建一个新的表,一个表的视图,或者数据库中的其他对象。 | 39 | | ALTER | 修改数据库中的某个已有的数据库对象,比如一个表。 | 40 | | DROP | 删除整个表,或者表的视图,或者数据库中的其他对象。 | 41 | 42 | **DML - 数据操作语言** 43 | 44 | | 命令 | 描述 | 45 | | :----- | :------------- | 46 | | INSERT | 创建一条记录。 | 47 | | UPDATE | 修改记录。 | 48 | | DELETE | 删除记录。 | 49 | 50 | **DQL - 数据查询语言** 51 | 52 | | 命令 | 描述 | 53 | | :----- | :----------------------------- | 54 | | SELECT | 从一个或多个表中检索某些记录。 | 55 | 56 | ![image-20240328165557012](C:\Users\chenx\AppData\Roaming\Typora\typora-user-images\image-20240328165557012.png) 57 | -------------------------------------------------------------------------------- /content/posts/专业/Frontend/包管理工具/yarn.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "yarn" 3 | date: 2021-12-05 4 | author: MelonCholi 5 | draft: false 6 | tags: [快速入门,前端,包管理器] 7 | categories: [前端] 8 | --- 9 | 10 | # yarn 11 | 12 | ## 基本操作 13 | 14 | ### 安装 15 | 16 | ```bash 17 | npm install -g yarn 18 | ``` 19 | 20 | ### 初始化一个新项目 21 | 22 | ```bash 23 | yarn init 24 | ``` 25 | 26 | ### 安装所有依赖项 27 | 28 | ```bash 29 | yarn 30 | yarn install 31 | ``` 32 | 33 | ### 添加依赖项 34 | 35 | ```bash 36 | yarn add [package] 37 | yarn add [package]@[version] 38 | yarn add [package]@[tag] 39 | ``` 40 | 41 | ### 将依赖项添加到不同的依赖类别中 42 | 43 | ```bash 44 | yarn add [package] --dev # dev dependencies 45 | yarn add [package] --peer # peer dependencies 46 | ``` 47 | 48 | ### 更新依赖项 49 | 50 | ```bash 51 | yarn up [package] 52 | yarn up [package]@[version] 53 | yarn up [package]@[tag] 54 | ``` 55 | 56 | ### 删除依赖项 57 | 58 | ```bash 59 | yarn remove [package] 60 | ``` 61 | 62 | ### 更新 Yarn 本体 63 | 64 | ```bash 65 | yarn set version latest 66 | yarn set version from sources 67 | ``` 68 | 69 | ## 与 vite 配合 70 | 71 | ### 运行 72 | 73 | ```bash 74 | yarn dev 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /content/posts/专业/Frontend/框架/Vue2.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/content/posts/专业/Frontend/框架/Vue2.md -------------------------------------------------------------------------------- /content/posts/专业/Golang/一些思考.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "关于 Go 的一些思考" 3 | date: 2023-05-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [并发] 7 | categories: [Golang] 8 | aliases: [关于 Go 的一些思考] 9 | date created: 24-04-10 17:04 10 | date modified: 24-04-11 02:44 11 | --- 12 | 13 | # 关于 Go 的一些思考 14 | 15 | ## Go 与依赖注入 16 | 17 | 依赖注入(Dependency Injection,简称 DI)是一种设计模式,它的主要目的是将**对象的创建和对象之间的依赖关系的解析过程从应用程序代码中分离出来**,交由框架或容器来管理(或者自己管理),从而降低代码复杂度。 18 | 19 | > 摘自 https://www.zhihu.com/question/265433666 20 | 21 | 在 Java 的世界中,工程师] 习惯于在写任何类型实现之前,都先定义一下类型所实现的接口,即便可能超过 80% 的情况下,相应的接口只有唯一的一个实现。 22 | 23 | 需要为唯一的一个实现定义接口(**以避免在替换实现时大幅修改代码**),这实际上是来自语言的特性的限制;要使用依赖注入,实际上也可以不通过接口注入,而直接注入具体类型的。 24 | 25 | Go 的接口可以迟于 struct 实现来定义这一独一无二的语言特性,使得我们在使用依赖注入的时可以先方便的注入具体类型;而在后续需要扩展为“接口”,提供多个实现的时候,无需修改模块代码! 26 | 27 | 可以说,Go 与依赖注入范式是相当绝妙的搭配。 28 | -------------------------------------------------------------------------------- /content/posts/专业/Golang/数据库操作/go-redis.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Go go-redis 库" 3 | date: 2022-02-14 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [数据库,后端, 未完工] 7 | categories: [Golang] 8 | --- 9 | 10 | # go-redis 11 | 12 | 官方文档:https://redis.uptrace.dev/zh/guide/go-redis.html 13 | -------------------------------------------------------------------------------- /content/posts/专业/Golang/标准库/网络/网络编程.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Go 基础语法" 3 | date: 2021-12-28 4 | draft: true 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [Golang] 8 | --- 9 | 10 | # web 工作方式 11 | 12 | https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/03.1.md -------------------------------------------------------------------------------- /content/posts/专业/Linux/Linux.md: -------------------------------------------------------------------------------- 1 | # Linux Overview 2 | 3 | ```ccard 4 | type: folder_brief_live 5 | ``` 6 | 7 | -------------------------------------------------------------------------------- /content/posts/专业/Linux/命令工具/bat.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "bat" 3 | date: 2022-01-13 4 | author: MelonCholi 5 | draft: false 6 | tags: [Linux,快速入门] 7 | categories: [Linux] 8 | --- 9 | 10 | # bat 11 | 12 | `bat` 是命令行下一款用来显示文件内容的工具,`bat` 命令功能跟常用命令 `cat` 类似。只是 `bat` 功能上更加强大一些,`bat` 在 `cat` 命令的基础上加入了行号显示、代码高亮和 Git 集成。 13 | 14 | 项目官方地址: `https://github.com/sharkdp/bat` 15 | 16 | ## 安装 17 | 18 | `bat` is available on [Ubuntu since 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) and [Debian since August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat). 19 | 20 | If your Ubuntu/Debian installation is new enough you can simply run: 21 | 22 | ``` 23 | sudo apt install bat 24 | ``` 25 | 26 | **Important**: If you install `bat` this way, please note that the executable may be installed as `batcat` instead of `bat` (due to [a name clash with another package](https://github.com/sharkdp/bat/issues/982)). You can set up a `bat -> batcat` symlink or alias to prevent any issues that may come up because of this and to be consistent with other distributions: 27 | 28 | ``` 29 | mkdir -p ~/.local/bin 30 | ln -s /usr/bin/batcat ~/.local/bin/bat 31 | ``` 32 | 33 | ## 示例 34 | 35 | ![image-20230113165553011](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230113165553011.png) -------------------------------------------------------------------------------- /content/posts/专业/Linux/命令工具/cloc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "cloc" 3 | date: 2021-10-23 4 | author: MelonCholi 5 | draft: false 6 | tags: [Linux,快速入门] 7 | categories: [Linux] 8 | --- 9 | 10 | # cloc 11 | 12 | 统计多种语言代码数据 13 | 14 | ```shell 15 | sudo apt-get install cloc 16 | ``` 17 | 18 | 命令 19 | 20 | ```shell 21 | cloc 22 | ``` 23 | 24 | ![image-20220125114847874](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220125114847874.png) -------------------------------------------------------------------------------- /content/posts/专业/Linux/命令工具/crontab.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "crontab" 3 | date: 2021-10-23 4 | author: MelonCholi 5 | draft: false 6 | tags: [Linux,快速入门] 7 | categories: [Linux] 8 | --- 9 | 10 | # crontab 11 | 12 | ```shell 13 | crontab -e 14 | ``` 15 | 16 | ## 时间语法 17 | 18 | ```bash 19 | # For details see man 4 crontabs 20 | 21 | # Example of job definition: 22 | # .---------------- minute (0 - 59) 23 | # | .------------- hour (0 - 23) 24 | # | | .---------- day of month (1 - 31) 25 | # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... 26 | # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat 27 | # | | | | | 28 | # * * * * * user-name command to be executed 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /content/posts/专业/Linux/命令工具/exa.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "exa" 3 | date: 2022-01-13 4 | author: MelonCholi 5 | draft: false 6 | tags: [Linux,快速入门] 7 | categories: [Linux] 8 | --- 9 | 10 | # exa 11 | 12 | > exa is a modern replacement for ls. 13 | 14 | 项目地址:https://github.com/ogham/exa 15 | 16 | ## 安装 17 | 18 | On Ubuntu 20.10 (Groovy Gorilla) and later, install the [`exa`](https://packages.ubuntu.com/jammy/exa) package. 19 | 20 | ``` 21 | sudo apt install exa 22 | ``` 23 | 24 | ## 使用 25 | 26 | `exa` 使用非常简单,其语法格式为 `exa [OPTIONS] [FILES]`,基本上和 `ls` 一样。 27 | 28 | 一行只输出一个结果 29 | 30 | ```sh 31 | $ exa -1 32 | ``` 33 | 34 | 输出结果并显示详细信息 35 | 36 | ```sh 37 | $ exa -l 38 | ``` 39 | 40 | 对比: 41 | 42 | image-20230113163739849 43 | 44 | 递归显示当然目录的所有文件 45 | 46 | > 输出结果的顺序为:先显示当前文件夹的,再递归显示每个子文件夹中的文件。 47 | 48 | ```sh 49 | $ exa -R 50 | ``` 51 | 52 | 以目录树结构显示目录下所有文件 53 | 54 | ```sh 55 | $ exa -T 56 | ``` 57 | 58 | 以网格方式排序 59 | 60 | ```sh 61 | $ exa -x 62 | ``` -------------------------------------------------------------------------------- /content/posts/专业/Linux/命令工具/tldr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "tldr" 3 | date: 2022-12-16 4 | author: MelonCholi 5 | draft: false 6 | tags: [Linux, 快速入门] 7 | categories: [Linux] 8 | --- 9 | 10 | # tldr 11 | 12 | https://github.com/isacikgoz/tldr 13 | 14 | 这里使用 go 安装 15 | 16 | ```sh 17 | go install github.com/isacikgoz/tldr@latest 18 | ``` 19 | 20 | 更新缓存,`tldr --update` 或 `tldr -u` 21 | 22 | 用 npm 安装 23 | 24 | https://github.com/tldr-pages/tldr 25 | 26 | ```shell 27 | npm install -g tldr 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /content/posts/专业/Linux/相关软件/NFS.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "NFS" 3 | date: 2021-03-16 4 | author: MelonCholi 5 | draft: false 6 | tags: [Linux] 7 | categories: [Linux] 8 | --- 9 | 10 | # NFS 11 | 12 | NFS 即网络文件系统(Network File-System),可以通过网络让不同机器、不同系统之间可以实现文件共享。通过 NFS,可以访问远程共享目录,就像访问本地磁盘一样。NFS 只是一种文件系统,本身并没有传输功能,是基于 RPC(远程过程调用)协议实现的,采用 C/S 架构。 13 | 14 | ## 搭建 NFS Server 15 | 16 | 安装 NFS 软件包 17 | ```shell 18 | sudo apt-get install nfs-kernel-server # 安装 NFS服务器端 19 | ``` 20 | 21 | 添加 NFS 共享目录 22 | 23 | ```shell 24 | sudo vim /etc/exports 25 | ``` 26 | 27 | 添加一行,把 “/nfsroot” 目录设置为 NFS 共享目录 28 | 29 | ```shell 30 | /nfsroot *(rw,sync,no_root_squash) # * 表示允许任何网段 IP 的系统访问该 NFS 目录 31 | ``` 32 | 33 | 新建“/nfsroot”目录,并为该目录设置最宽松的权限: 34 | 35 | ```shell 36 | sudo mkdir /nfsroot 37 | sudo chmod -R 777 /nfsroot 38 | sudo chown ipual:ipual /nfsroot/ -R # ipual 为当前用户,-R 表示递归更改该目录下所有文件 39 | ``` 40 | 41 | 启动 NFS 服务 42 | 43 | ```shell 44 | sudo /etc/init.d/nfs-kernel-server start 45 | # or 46 | sudo /etc/init.d/nfs-kernel-server restart 47 | ``` 48 | 49 | 在 NFS 服务已经启动的情况下,如果修改了 “/etc/exports” 文件,需要重启 NFS 服务,以刷新 NFS 的共享目录。 50 | 51 | ## NFS Client 配置 52 | 53 | 安装客户端 54 | 55 | ```shell 56 | sudo apt-get install nfs-common # 安装 NFS客户端 57 | ``` 58 | 59 | 挂载 60 | 61 | ```shell 62 | sudo mount -t nfs 192.168.163.128:/nfsroot /mnt -o nolock 63 | ``` 64 | 65 | 192.168.12.123 为主机 ip,/nfsroot 为主机共享目录,/mnt 为设备挂载目录,如果指令运行没有出错,则 NFS 挂载成功,在主机的 /mnt 目录下应该可以看到 /nfsroot 目录下的内容(可先在 nfsroot 目录下新建测试目录), 66 | 67 | 卸载: 68 | 69 | ```shell 70 | umount /mnt 71 | ``` 72 | 73 | 若要开机自动挂载,在 /etc/fstab 里添加 74 | 75 | ```shell 76 | 192.168.12.123:/nfsroot /mnt nfs rw 0 0 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /content/posts/专业/Lua/BasicGrammar.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Lua 基础语法" 3 | date: 2021-12-25 4 | author: MelonCholi 5 | draft: true 6 | tags: [Lua] 7 | categories: [Lua] 8 | --- 9 | 10 | # BasicGrammar 11 | 12 | > 参考:https://blog.ginshio.org/2022/dst_lua_language_study/ -------------------------------------------------------------------------------- /content/posts/专业/Python/Python.md: -------------------------------------------------------------------------------- 1 | --- 2 | obsidianUIMode: preview 3 | aliases: [Python Overview] 4 | date created: 24-04-17 17:44 5 | date modified: 24-04-18 11:23 6 | --- 7 | 8 | # Python Overview 9 | 10 | ```ccard 11 | type: folder_brief_live 12 | ``` 13 | -------------------------------------------------------------------------------- /content/posts/专业/Python/WEB backend/Pydantic/10. Validators.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: pydantic validators 3 | date: 2024-04-23 4 | author: CoengFan 5 | draft: false 6 | tags: 7 | categories: 8 | date created: 24-04-23 18:04 9 | date modified: 24-04-23 18:05 10 | --- 11 | 12 | # 10. Validators 13 | -------------------------------------------------------------------------------- /content/posts/专业/Python/WEB backend/Pydantic/Pydantic.md: -------------------------------------------------------------------------------- 1 | --- 2 | obsidianUIMode: preview 3 | --- 4 | # Pydantic Overview 5 | 6 | ```ccard 7 | type: folder_brief_live 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /content/posts/专业/Python/可视化/rich/column.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Python rich 库 - Column" 3 | date: 2022-12-02 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # Column 11 | 12 | Rich 可以通过 `Columns` 类在整齐的列中渲染文本或其他 Rich 渲染物。 13 | 14 | To use, construct a Columns instance with an iterable of renderables and print it to the Console. 15 | 16 | The following example is a very basic clone of the `ls` command in OSX / Linux to list directory contents: 17 | 18 | ```py 19 | import os 20 | import sys 21 | 22 | from rich import print 23 | from rich.columns import Columns 24 | 25 | if len(sys.argv) < 2: 26 | print("Usage: python columns.py DIRECTORY") 27 | else: 28 | directory = os.listdir(sys.argv[1]) 29 | columns = Columns(directory, equal=True, expand=True) 30 | print(columns) 31 | ``` 32 | 33 | See [columns.py](https://github.com/willmcgugan/rich/blob/master/examples/columns.py) for an example which outputs columns containing more than just text. -------------------------------------------------------------------------------- /content/posts/专业/Python/字节码.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/content/posts/专业/Python/字节码.md -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/apscheduler.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "apscheduler" 3 | date: 2021-04-17 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # apscheduler 11 | 12 | https://www.cnblogs.com/gdjlc/p/11432526.html -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/bisect.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "bisect" 3 | date: 2021-04-17 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/getpot.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Trouvaille0198/Notes/c2757f1ee64233969a039552275c08fe4326eeb9/content/posts/专业/Python/常用库/getpot.md -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/importlib.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "importlib" 3 | date: 2021-08-15 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # importlib 11 | 12 | 文件结构 13 | 14 | ```python 15 | a #文件夹 16 | │a.py 17 | │__init__.py 18 | b #文件夹 19 | │b.py 20 | │__init__.py 21 | ├─c#文件夹 22 | │c.py 23 | │__init__.py 24 | 25 | # c.py 中内容 26 | args = {'a':1} 27 | 28 | class C: 29 | 30 | def c(self): 31 | pass 32 | ``` 33 | 34 | 向 a 模块中导入 c.py 中的对象 35 | 36 | ```python 37 | import importlib 38 | 39 | params = importlib.import_module('b.c.c') #绝对导入 40 | params_ = importlib.import_module('.c.c',package='b') #相对导入 41 | 42 | # 对象中取出需要的对象 43 | params.args #取出变量 44 | params.C #取出class C 45 | params.C.c #取出class C 中的c 方法 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/ipdb.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Python ipdb 库" 3 | date: 2022-09-15 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # ipdb 11 | 12 | ## 介绍 13 | 14 | 是一款集成了 Ipython 的 Python 代码命令行调试工具,可以看做 PDB 的升级版 15 | 16 | 开发一直是在 pycharm 下,虽然 pycharm 可以断点调试,但是程序是一直往下走的,没法像 Viso 那样拖动当前的位置,如果发现某个地方因为数据导致有问题,需要断开调试,修改完数据后,再次 debug,很废时间。而 ipdb 可以通过 **jump 行数**任意各种跳,相当方便 17 | 18 | ## 启动 19 | 20 | ### 命令式 21 | 22 | `python -m ipdb xxx.py` 单步调试 23 | 24 | ### 集成式 25 | 26 | 在需要断点的地方插入两句话 27 | 28 | ```py 29 | import ipdb 30 | ipdb.set_trace() 31 | ``` 32 | 33 | - 运行程序后, 会在执行到 set_trace()的时候中断程序 并出现提示符 34 | - `ipdb>` 35 | - 好像进入了 ipython 一样 36 | 37 | ## 常用命令 38 | 39 | - h (help) - 帮助文档 40 | - l (list) 开始行,结束行 - 查看指定行数之间的代码(逗号很重要),如果不带结束行,则显示开始行的上下 5 行。 41 | - w (where) - 打印目前所在的行号位置以及上下文信息。 42 | - j (jump) 行 - 跳转到指定行。 43 | - n (next) - 单步执行。函数调用也是一个语句。 44 | - s (step|step next) - 进入函数内部。 45 | - a (args) - 进入函数内部后,打印函数的所有参数。 46 | - u (up) - 跳回上一层调用,只是在代码层面跳转,程序执行到哪一步还是在哪一步,不信可以用 n 命令试一下。 47 | - d (down) - 跳到调用的下一层,只是在代码层面跳转,程序执行到哪一步还是在哪一步,不信可以用 n 命令试一下。 48 | - b (break) [ ([filename:]lineno | function) [, condition] ] - 在指定文件(不指定,默认当前文件)指定行 打断点 49 | - p (print) 变量 - 打印变量的值 50 | - pp (pretty print) 变量 - 格式化打印变量的值 51 | - c (continue) - 继续运行,直到遇到下一个断点 52 | - cl (clear) filename:lineno - 清除断点(只能清除交互调试中打的断点,在代码中 set_trace()是无法清除的) 53 | - r (return) - 继续运行直到函数返回(函数内 return 语句,如果没有返回值,则跳到函数的最后) 54 | - restart - 重新启动调试器,断点等信息都会保留 55 | - q (quit) - 退出调试模式 56 | - 变量名 - 查看变量内容 57 | - ! 变量名 - 如果代码中变量名与 ipdb 命令冲突,则使用 **!** 解决冲突。 58 | -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/loguru.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "loguru" 3 | date: 2021-04-17 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # loguru 11 | 12 | 比 logging 更加轻便简单的日志记录器 13 | 14 | ## 基本使用 15 | 16 | ```python 17 | from loguru import logger 18 | import os 19 | import time 20 | 21 | LOG_FOLDER = os.getcwd()+'\\logs' 22 | if not os.path.exists(LOG_FOLDER): 23 | os.mkdir(LOG_FOLDER) 24 | t = time.strftime("%Y_%m_%d") 25 | logger = logger 26 | logger.add("{}\\log_{}.log".format(LOG_FOLDER, t), 27 | rotation="00:00", encoding="utf-8", retention="300 days") 28 | 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/pyinstaller.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "pyinstaller" 3 | date: 2021-04-17 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # pyinstaller 11 | 12 | ## 步骤 13 | 14 | 1. 在 cmd 中使用命令找到 py 程序所在目录 15 | 2. 使用命令 16 | 17 | ```shell 18 | pyinstaller -F .py 19 | ``` 20 | 21 | ​ dist 文件夹中的 exe 即为我们所需要的可执行文件 22 | 23 | ## 常用参数 24 | 25 | 语法 26 | 27 | ```shell 28 | pyinstaller 选项 Python 源文件 29 | ``` 30 | 31 | | 参数 | 描述 | 32 | | :------------------ | :--------------------------------- | 33 | | -h | 查看帮助 | 34 | | --clean | 清理打包过程中的临时文件 | 35 | | -D, --onedir | 默认值,生成dist文件夹 | 36 | | -F, --onefile | 在dist文件夹中只生成独立的打包文件 | 37 | | -i <图标文件名.ico> | 指定打包程序使用的图标(icon)文件 | 38 | 39 | -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/random.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Python random 库" 3 | date: 2021-10-23 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # random 11 | 12 | ## 认识 13 | 14 | 生成各种随机数 15 | 16 | ### 导入 17 | 18 | ```python 19 | import random 20 | ``` 21 | 22 | 模块中主要使用 `random` 类 23 | 24 | ## API 25 | 26 | 下述方法均为 `random` 类的成员函数 27 | 28 | ### 基本 29 | 30 | - ***random()*** 31 | 32 | 生成 `[0,1)` 的随机浮点数 33 | 34 | - ***seed(a: int=None)*** 35 | 36 | 初始化随机数生成器 37 | 38 | - *a*:随机数种子。若空,则使用当前系统时间 39 | 40 | - ***uniform(a: float, b: float)*** 41 | 42 | 生成浮点数 43 | 44 | - ***randint(a: int, b: int)*** 45 | 46 | 生成整型数 47 | 48 | - ***randrange(start, stop[, step])*** 49 | 50 | 从 *range(start, stop[, step])* 中随机选择一个元素 51 | 52 | - ***choice(seq)*** 53 | 54 | 从序列 seq 中获取一个随机元素 55 | 56 | - ***shuffle(seq)*** 57 | 58 | 将序列 seq 中的元素打乱,不返回,会打乱原有序列 59 | 60 | 要改变一个不可变的序列并返回一个新的打乱列表,请使用 ``sample(x, k=len(x))`` 61 | 62 | - ***sample(seq, len)*** 63 | 64 | 从序列 seq 中随机获取指定长度 len 的片段并返回 65 | 66 | ### 分布 67 | 68 | - ***normalvariate(mu, sigma)*** 69 | 70 | 返回符合指定均值方差的正态分布的一个随机数 71 | 72 | ```python 73 | c = [random.normalvariate(15, 10) for i in range(1000)] 74 | ``` 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/ruff.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ruff 3 | date: 2024-04-18 4 | author: CoengFan 5 | draft: false 6 | tags: [Python] 7 | categories: 8 | - Python 9 | date created: 24-04-18 15:00 10 | date modified: 24-04-18 15:22 11 | --- 12 | 13 | # ruff 14 | 15 | [Tutorial - Ruff](https://docs.astral.sh/ruff/tutorial/#getting-started) 16 | -------------------------------------------------------------------------------- /content/posts/专业/Python/常用库/tqdm.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "tqdm" 3 | date: 2021-04-17 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # tqdm 11 | 12 | Tqdm 是一个快速,可扩展的 Python 进度条,可以在 Python 长循环中添加一个进度提示信息,用户只需要封装任意的迭代器`tqdm(iterator)`。 13 | 14 | ***`tqdm(iterator, color)`*** 15 | 16 | ## 使用方法一: tqdm 17 | 18 | `tqdm(list)` 方法可以传入任意一种 list,比如数组 19 | 20 | ```python 21 | from tqdm import tqdm 22 | 23 | for i in tqdm(range(1000)): 24 | #do something 25 | pass 12345 26 | ``` 27 | 28 | 或者 string 的数组 29 | 30 | ```python 31 | for char in tqdm(["a", "b", "c", "d"]): 32 | #do something 33 | pass123 34 | ``` 35 | 36 | ## 使用方法二: trange 37 | 38 | `trange(i)` 是 `tqdm(range(i))` 的简单写法 39 | 40 | ```python 41 | from tqdm import trange 42 | for i in trange(100): 43 | #do something 44 | pass1234 45 | ``` 46 | 47 | ## .set_description() 48 | 49 | 实时查看每次处理的数据 50 | 51 | ```python 52 | from tqdm import tqdm 53 | import time 54 | 55 | pbar = tqdm(["a","b","c","d"]) 56 | for c in pbar: 57 | time.sleep(1) 58 | pbar.set_description("Processing %s"%c) 59 | ``` 60 | 61 | ![image-20210213224128056](http://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20210213224128056.png) 62 | 63 | ## 控制进度 64 | 65 | ```python 66 | from tqdm import tqdm 67 | import time 68 | 69 | #total参数设置进度条的总长度 70 | with tqdm(total=100) as pbar: 71 | for i in range(100): 72 | time.sleep(0.05) 73 | #每次更新进度条的长度 74 | pbar.update(1) 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /content/posts/专业/Python/数据库交互/motor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Python motor 库" 3 | date: 2023-8-1 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python, 数据库交互] 7 | categories: [Python] 8 | --- 9 | 10 | # motor 11 | 12 | motor 用来异步地操作 MongoDB 13 | 14 | TODO:https://www.cnblogs.com/aduner/p/13532504.html -------------------------------------------------------------------------------- /content/posts/专业/Python/标准库/pytest.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "pytest" 3 | date: 2023-10-12 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | --- 9 | 10 | # pytest 11 | 12 | -------------------------------------------------------------------------------- /content/posts/专业/Python/版本管理/pyenv.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | # pyenv 6 | 7 | ## 常用命令 8 | 9 | ```bash 10 | pyenv install --list # 列出可安装版本 11 | pyenv install # 安装对应版本 12 | pyenv install -v # 安装对应版本,若发生错误,可以显示详细的错误信息 13 | pyenv versions # 显示当前使用的python版本 14 | pyenv which python # 显示当前python安装路径 15 | pyenv global # 设置默认Python版本 16 | pyenv local # 当前路径创建一个.python-version, 以后进入这个目录自动切换为该版本 17 | pyenv shell # 当前shell的session中启用某版本,优先级高于global 及 local 18 | ``` -------------------------------------------------------------------------------- /content/posts/专业/Python/版本管理/virtualenv.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | # virtualenv 6 | 7 | ## 常用命令 8 | 9 | 创建虚拟环境 10 | 11 | ```sh 12 | mkvirtualenv --python=python3.7 venvname 13 | ``` 14 | 15 | 查看已经创建的虚拟环境 16 | 17 | ```sh 18 | workon 19 | ``` 20 | 21 | 激活虚拟环境 22 | 23 | ```sh 24 | workon venvename 25 | ``` 26 | 27 | 删除虚拟环境 28 | 29 | ```sh 30 | rmvirtualenv venvname 31 | ``` -------------------------------------------------------------------------------- /content/posts/专业/Python/特性.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Python 特性" 3 | date: 2022-01-18 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | date created: 24-04-10 09:58 9 | date modified: 24-04-18 10:24 10 | --- 11 | 12 | # 特性 13 | 14 | ## 特殊方法 15 | 16 | 也叫魔术方法、双下方法(dunder method) 17 | 18 | ## 迭代器 19 | 20 | ### 生成器 21 | -------------------------------------------------------------------------------- /content/posts/专业/Python/配置 jupyter-lab.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "配置 jupyter-lab" 3 | date: 2023-09-27 4 | author: MelonCholi 5 | draft: false 6 | tags: [Python] 7 | categories: [Python] 8 | date created: 24-04-10 09:58 9 | date modified: 24-04-18 10:24 10 | --- 11 | 12 | # 配置 jupyter-lab 13 | 14 | ## 安装 15 | 16 | 一些配置 17 | 18 | image-20230927135241580 19 | 20 | ## 主题 21 | 22 | [catppuccin_jupyterlab](https://github.com/catppuccin/jupyterlab) 23 | 24 | ```sh 25 | pip install catppuccin-jupyterlab 26 | ``` 27 | 28 | Go to the `Settings > Theme` menu option and choose the desired flavor. 29 | 30 | ## 插件 31 | -------------------------------------------------------------------------------- /content/posts/专业/专业.md: -------------------------------------------------------------------------------- 1 | --- 2 | obsidianUIMode: preview 3 | --- 4 | # 专业 Overview 5 | 6 | ```ccard 7 | type: folder_brief_live 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/152. 乘积最大子数组.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "152. 乘积最大子数组" 3 | date: 2022-02-25 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | --- 9 | 10 | # 152. 乘积最大子数组 11 | 12 | `mid` 13 | 14 | 给你一个整数数组 `nums` ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 15 | 16 | 测试用例的答案是一个 **32-位** 整数。 17 | 18 | **子数组** 是数组的连续子序列。 19 | 20 | **示例 1:** 21 | 22 | ``` 23 | 输入: nums = [2,3,-2,4] 24 | 输出: 6 25 | 解释: 子数组 [2,3] 有最大乘积 6。 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入: nums = [-2,0,-1] 32 | 输出: 0 33 | 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 34 | ``` 35 | 36 | ## DP 37 | 38 | 非常神奇的一道题目 39 | 40 | ![image-20220802201431433](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220802201431433.png) 41 | 42 | ```go 43 | func maxProduct(nums []int) int { 44 | maxRes, minRes, res := nums[0], nums[0], nums[0] 45 | for i := 1; i < len(nums); i++ { 46 | maxTmp, minTmp := maxRes, minRes 47 | maxRes = max(maxTmp*nums[i], max(minTmp*nums[i], nums[i])) 48 | minRes = min(minTmp*nums[i], min(maxTmp*nums[i], nums[i])) 49 | res := max(maxRes, res) 50 | } 51 | return res 52 | } 53 | 54 | func max(a, b int) int { 55 | if a > b { 56 | return a 57 | } else { 58 | return b 59 | } 60 | } 61 | 62 | func min(a, b int) int { 63 | if a < b { 64 | return a 65 | } else { 66 | return b 67 | } 68 | } 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/2100. 适合打劫银行的日子.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "2100. 适合打劫银行的日子" 3 | date: 2022-03-14 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 2100. 适合打劫银行的日子 12 | 13 | `mid` 14 | 15 | 你和一群强盗准备打劫银行。给你一个下标从 **0** 开始的整数数组 `security` ,其中 `security[i]` 是第 `i` 天执勤警卫的数量。日子从 `0` 开始编号。同时给你一个整数 `time` 。 16 | 17 | 如果第 `i` 天满足以下所有条件,我们称它为一个适合打劫银行的日子: 18 | 19 | - 第 `i` 天前和后都分别至少有 `time` 天。 20 | - 第 `i` 天前连续 `time` 天警卫数目都是非递增的。 21 | - 第 `i` 天后连续 `time` 天警卫数目都是非递减的。 22 | 23 | 请你返回一个数组,包含 **所有** 适合打劫银行的日子(下标从 **0** 开始)。返回的日子可以 **任意** 顺序排列。 24 | 25 | **示例 1:** 26 | 27 | ``` 28 | 输入:security = [5,3,3,3,5,6,2], time = 2 29 | 输出:[2,3] 30 | ``` 31 | 32 | **示例 2:** 33 | 34 | ``` 35 | 输入:security = [1,1,1,1,1], time = 0 36 | 输出:[0,1,2,3,4] 37 | ``` 38 | 39 | **示例 3:** 40 | 41 | ``` 42 | 输入:security = [1,2,3,4,5,6], time = 2 43 | 输出:[] 44 | ``` 45 | 46 | ## 动态规划 47 | 48 | 把第 i 天前非递增天数和第 i 天非递减天数求出来就可以了 49 | 50 | ```go 51 | func goodDaysToRobBank(security []int, time int) []int { 52 | res := make([]int, 0) 53 | dp1 := make([]int, len(security)) 54 | dp1[0] = 0 55 | for i := 1; i < len(security); i++ { 56 | if security[i-1] >= security[i] { 57 | dp1[i] = dp1[i-1] + 1 58 | } else { 59 | dp1[i] = 0 60 | } 61 | } 62 | dp2 := make([]int, len(security)) 63 | dp2[len(security)] = 0 64 | for i := len(security) - 1; i >= 0; i-- { 65 | if security[i] <= security[i+1] { 66 | dp2[i] = dp2[i+1] + 1 67 | } else { 68 | dp2[i] = 0 69 | } 70 | } 71 | 72 | for i := time; i < len(security)-time; i++ { 73 | if dp1[i] >= time && dp2[i] >= time { 74 | res = append(res, i) 75 | } 76 | } 77 | return res 78 | } 79 | ``` 80 | 81 | 前两个 for 循环还能合到一起,不过懒得合了 -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/279. 完全平方数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "279. 完全平方数" 3 | date: 2022-08-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 279. 完全平方数 12 | 13 | `mid` 14 | 15 | 给你一个整数 `n` ,返回 *和为 `n` 的完全平方数的最少数量* 16 | 17 | **完全平方数** 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,`1`、`4`、`9` 和 `16` 都是完全平方数,而 `3` 和 `11` 不是。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:n = 12 23 | 输出:3 24 | 解释:12 = 4 + 4 + 4 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:n = 13 31 | 输出:2 32 | 解释:13 = 4 + 9 33 | ``` 34 | 35 | ## DP 36 | 37 | ![image-20220810142942929](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220810142942929.png) 38 | 39 | ```go 40 | func numSquares(n int) int { 41 | dp := make([]int, n+1) 42 | for i := 1; i <= n; i++ { 43 | minCnt := math.MaxInt32 44 | for j := 1; j*j <= i; j++ { 45 | minCnt = min(minCnt, dp[i-j*j]) 46 | } 47 | dp[i] = minCnt + 1 48 | } 49 | return dp[n] 50 | } 51 | 52 | func min(a, b int) int { 53 | if a < b { 54 | return a 55 | } 56 | return b 57 | } 58 | ``` 59 | 60 | ![image-20220810143013425](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220810143013425.png) -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/309. 最佳买卖股票时机含冷冻期.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "309. 最佳买卖股票时机含冷冻期" 3 | date: 2022-08-11 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 309. 最佳买卖股票时机含冷冻期 12 | 13 | `mid` 14 | 15 | 给定一个整数数组`prices`,其中第 `prices[i]` 表示第 `*i*` 天的股票价格 。 16 | 17 | 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 18 | 19 | - 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天) 20 | 21 | **注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 22 | 23 | **示例 1:** 24 | 25 | ``` 26 | 输入: prices = [1,2,3,0,2] 27 | 输出: 3 28 | 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出] 29 | ``` 30 | 31 | **示例 2:** 32 | 33 | ``` 34 | 输入: prices = [1] 35 | 输出: 0 36 | ``` 37 | 38 | ## DP + 状态机 39 | 40 | `dp[i][0]` 代表第 i 天持有股票 41 | `dp[i][1] ` 代表第 i 天没有股票 42 | `dp[i][2] ` 代表第 i 天是冷冻期 43 | 44 | image-20220811133249648 45 | 46 | 我们只需要返回最后一天没有持有股票的最大利润即可,也就是 `return dp[prices.length - 1][0];` 47 | 48 | ```go 49 | func maxProfit(prices []int) int { 50 | dp := make([][]int, len(prices)) 51 | for i := 0; i < len(prices); i++ { 52 | dp[i] = make([]int, 3) 53 | } 54 | 55 | dp[0] = []int{-prices[0], 0, 0} 56 | 57 | for i := 1; i < len(prices); i++ { 58 | // 持有股票 59 | dp[i][0] = max(dp[i-1][0], dp[i-1][2]-prices[i]) // 之前的/冷冻期后新买的 60 | // 不持有股票 61 | dp[i][1] = max(dp[i-1][0]+prices[i], dp[i-1][1]) // 今天卖掉了/之前就没有 62 | // 冷冻期 63 | dp[i][2] = dp[i-1][1] // 昨天卖掉的 64 | } 65 | return dp[len(prices)-1][1] 66 | } 67 | 68 | func max(a, b int) int { 69 | if a > b { 70 | return a 71 | } 72 | return b 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/322. 零钱兑换.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "322. 零钱兑换" 3 | date: 2022-08-12 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 322. 零钱兑换 12 | 13 | `mid` 14 | 15 | 给你一个整数数组 `coins` ,表示不同面额的硬币;以及一个整数 `amount` ,表示总金额。 16 | 17 | 计算并返回可以凑成总金额所需的 **最少的硬币个数** 。如果没有任何一种硬币组合能组成总金额,返回 `-1` 。 18 | 19 | 你可以认为每种硬币的数量是无限的。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:coins = [1, 2, 5], amount = 11 25 | 输出:3 26 | 解释:11 = 5 + 5 + 1 27 | ``` 28 | 29 | **示例 2:** 30 | 31 | ``` 32 | 输入:coins = [2], amount = 3 33 | 输出:-1 34 | ``` 35 | 36 | **示例 3:** 37 | 38 | ``` 39 | 输入:coins = [1], amount = 0 40 | 输出:0 41 | ``` 42 | 43 | ## DP 44 | 45 | 经典 DP 46 | $$ 47 | dp[amount]=min(dp[amount−coin])+1 \\ 48 | for \ coin \ in \ coins 49 | $$ 50 | 51 | ```go 52 | import "math" 53 | 54 | func coinChange(coins []int, amount int) int { 55 | dp := make([]int, amount+1) 56 | for i := 1; i <= amount; i++ { 57 | dp[i] = -1 58 | } 59 | 60 | for i := 0; i <= amount; i++ { 61 | minVal := math.MaxInt32 62 | for _, coin := range coins { 63 | if i-coin >= 0 && dp[i-coin] != -1 && dp[i-coin]+1 < minVal { 64 | // 硬币面额小于等于i && dp[找零]存在 && dp[找零]+1暂时最小 65 | minVal = dp[i-coin] + 1 66 | } 67 | } 68 | if minVal != math.MaxInt32 { 69 | dp[i] = minVal 70 | } 71 | } 72 | return dp[amount] 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/338. 比特位计数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "338. 比特位计数" 3 | date: 2022-08-15 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 338. 比特位计数 12 | 13 | `easy` 14 | 15 | 给你一个整数 `n` ,对于 `0 <= i <= n` 中的每个 `i` ,计算其二进制表示中 **`1` 的个数** ,返回一个长度为 `n + 1` 的数组 `ans` 作为答案。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:n = 2 21 | 输出:[0,1,1] 22 | 解释: 23 | 0 --> 0 24 | 1 --> 1 25 | 2 --> 10 26 | ``` 27 | 28 | ## DP 29 | 30 | 考虑奇数、偶数两种情况 31 | 32 | ![image-20220815112622104](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220815112622104.png) 33 | 34 | ```go 35 | func countBits(n int) []int { 36 | dp := make([]int, n+1) 37 | dp[0] = 0 38 | for i := 1; i <= n; i++ { 39 | dp[i] = dp[i>>1] + i&1 40 | } 41 | return dp 42 | } 43 | ``` 44 | 45 | image-20220815112630113 -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/62. 不同路径.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "62. 不同路径" 3 | date: 2022-07-04 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp, 数学] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 62. 不同路径 12 | 13 | `mid` 14 | 15 | 一个机器人位于一个 `m x n` 网格的左上角 (起始点在下图中标记为 “Start” ) 16 | 17 | 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 18 | 19 | 问总共有多少条不同的路径? 20 | 21 | ![image-20220704223241186](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220704223241186.png) 22 | 23 | ## dp 24 | 25 | ![image-20220704223316342](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220704223316342.png) 26 | 27 | ```go 28 | func uniquePaths(m, n int) int { 29 | dp := make([][]int, m) 30 | for i := 0; i < m; i++ { 31 | dp[i] = make([]int, n) 32 | dp[i][0] = 1 33 | } 34 | for j := 0; j < n; j++ { 35 | dp[0][j] = 1 36 | } 37 | for i := 1; i < m; i++ { 38 | for j := 1; j < n; j++ { 39 | dp[i][j] = dp[i-1][j] + dp[i][j-1] 40 | } 41 | } 42 | return dp[m-1][n-1] 43 | } 44 | ``` 45 | 46 | ## 数学 47 | 48 | ![image-20220704223347884](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220704223347884.png) 49 | 50 | ```go 51 | func uniquePaths(m, n int) int { 52 | return int(new(big.Int).Binomial(int64(m+n-2), int64(n-1)).Int64()) 53 | } 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/96. 不同的二叉搜索树.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "96. 不同的二叉搜索树" 3 | date: 2022-03-17 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 96. 不同的二叉搜索树 12 | 13 | 给你一个整数 `n` ,求恰由 `n` 个节点组成且节点值从 `1` 到 `n` 互不相同的 **二叉搜索树** 有多少种?返回满足题意的二叉搜索树的种数。 14 | 15 | ![image-20220317201424161](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220317201424161.png) 16 | 17 | ## DP 18 | 19 | ![image-20220317201731346](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220317201731346.png) 20 | 21 | 每次只遍历一半会更快。 22 | 23 | ```go 24 | func numTrees(n int) int { 25 | dp := make([]int, n+1) 26 | dp[0], dp[1] = 1, 1 27 | for i := 2; i <= n; i++ { 28 | for j := 1; j <= i/2; j++ { 29 | // 遍历每一个结点作为头节点 因为是对称的情况所以可以遍历一半 30 | dp[i] += dp[j-1] * dp[i-j] 31 | } 32 | dp[i] *= 2 33 | if i%2 == 1 { 34 | // 单独处理奇数的情况 35 | dp[i] += dp[i/2] * dp[i/2] 36 | } 37 | } 38 | return dp[n] 39 | } 40 | ``` 41 | 42 | ![image-20220317201930778](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220317201930778.png) 43 | 44 | ## 递归 45 | 46 | 思路一致,不过超时了…… 47 | 48 | ```go 49 | // 易于理解的递归思路 50 | func numTrees(n int) int { 51 | if n == 1 || n == 0 { 52 | return 1 53 | } 54 | sum := 0 55 | for i := 1; i <= n; i++ { 56 | // 遍历每一个结点作为头结点 57 | sum += numTrees(i-1) * numTrees(n-i) 58 | } 59 | return sum 60 | } 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/剑指 Offer 10- I. 斐波那契数列.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 10- I. 斐波那契数列 2 | 3 | `easy` 4 | 5 | 写一个函数,输入 `n` ,求斐波那契(Fibonacci)数列的第 `n` 项(即 `F(N)`)。斐波那契数列的定义如下: 6 | 7 | ``` 8 | F(0) = 0, F(1) = 1 9 | F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 10 | ``` 11 | 12 | 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 13 | 14 | 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 15 | 16 | **示例 1:** 17 | 18 | ``` 19 | 输入:n = 2 20 | 输出:1 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:n = 5 27 | 输出:5 28 | ``` 29 | 30 | ## 解 31 | 32 | 还省去了一张 O(n) 的表,妙哉 33 | 34 | ```go 35 | // DP 36 | func fib2(n int) int { 37 | const mod int = 1e9 + 7 38 | if n < 2 { 39 | return n 40 | } 41 | a, b, sum := 0, 0, 1 42 | for i := 2; i <= n; i++ { 43 | a = b 44 | b = sum 45 | sum = (a + b) % mod 46 | } 47 | return sum 48 | } 49 | ``` 50 | 51 | ```go 52 | func totalFruit(fruits []int) int { 53 | if len(fruits) == 0 { 54 | return 0 55 | } 56 | dp := make([]int, len(fruits)) 57 | dp[0] = 1 58 | a, b, aIndex, bIndex := -1, fruits[0], -1, 0 59 | maxResult := 1 60 | for i := 1; i < len(fruits); i++ { 61 | if fruits[i] == a || fruits[i] == b { 62 | // 加老果子 63 | if fruits[i] == a { 64 | aIndex = i 65 | } 66 | if fruits[i] == b { 67 | bIndex = i 68 | } 69 | dp[i] = dp[i-1] + 1 70 | } else { 71 | // 换新果子 72 | var length int 73 | // 计算最近一类果实的长度 并覆盖掉丢弃果子的种类 74 | if aIndex > bIndex { 75 | length = aIndex - bIndex 76 | b = fruits[i] 77 | bIndex = i 78 | } else { 79 | length = bIndex - aIndex 80 | a = fruits[i] 81 | aIndex = i 82 | } 83 | dp[i] = length + 1 84 | } 85 | if maxResult < dp[i] { 86 | maxResult = dp[i] 87 | } 88 | } 89 | return maxResult 90 | } 91 | ``` 92 | 93 | ## 滑动窗口 94 | 95 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/剑指 Offer 10- II. 青蛙跳台阶问题.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 10- II. 青蛙跳台阶问题 2 | 3 | 一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。 4 | 5 | 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 6 | 7 | **示例 1:** 8 | 9 | ``` 10 | 输入:n = 2 11 | 输出:2 12 | ``` 13 | 14 | **示例 2:** 15 | 16 | ``` 17 | 输入:n = 7 18 | 输出:21 19 | ``` 20 | 21 | **示例 3:** 22 | 23 | ``` 24 | 输入:n = 0 25 | 输出:1 26 | ``` 27 | 28 | ## 解 29 | 30 | 这就是斐波那契数列嘛 31 | 32 | ```go 33 | func numWays(n int) int { 34 | const mod = 1e9 + 7 35 | a, b, sum := 0, 1, 1 36 | for i := 2; i <= n; i++ { 37 | a = b 38 | b = sum 39 | sum = (a + b) % mod 40 | } 41 | return sum 42 | } 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/剑指 Offer 42. 连续子数组的最大和.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 42. 连续子数组的最大和 2 | 3 | `easy` 4 | 5 | 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。 6 | 7 | 要求时间复杂度为 O(n)。 8 | 9 | **示例1:** 10 | 11 | ``` 12 | 输入: nums = [-2,1,-3,4,-1,2,1,-5,4] 13 | 输出: 6 14 | 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 15 | ``` 16 | 17 | ## DP 18 | 19 | 用 dp(i) 代表以第 i 个数结尾的「连续子数组的最大和」 20 | 21 | dp(i) = max{ dp(i−1) + nums[i], nums[i] } 22 | 23 | ```go 24 | func maxSubArray(nums []int) int { 25 | dp := make([]int, len(nums)) 26 | dp[0] = nums[0] 27 | maxResult := dp[0] 28 | for i := 1; i < len(nums); i++ { 29 | if dp[i-1]+nums[i] > nums[i] { 30 | dp[i] = dp[i-1] + nums[i] 31 | } else { 32 | dp[i] = nums[i] 33 | } 34 | if dp[i] > maxResult { 35 | maxResult = dp[i] 36 | } 37 | } 38 | return maxResult 39 | } 40 | ``` 41 | 42 | ## 更简便的方法 43 | 44 | 因为 dp[i] 只与 dp[i-1] 相关,所以用一个 pre 变量接住 dp[i-1] 将空间复杂度降至 O(1) 45 | 46 | ```go 47 | func maxSubArray(nums []int) int { 48 | maxResult := nums[0] 49 | pre := nums[0] 50 | for i := 1; i < len(nums); i++ { 51 | if pre > 0 { 52 | pre = pre + nums[i] 53 | } else { 54 | pre = nums[i] 55 | } 56 | if pre > maxResult { 57 | maxResult = pre 58 | } 59 | } 60 | return maxResult 61 | } 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/DP/剑指 Offer 46. 把数字翻译成字符串.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 46. 把数字翻译成字符串 2 | 3 | `mid` 4 | 5 | 给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。 6 | 7 | **示例 1:** 8 | 9 | ``` 10 | 输入: 12258 11 | 输出: 5 12 | 解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi" 13 | ``` 14 | 15 | ## DP 16 | 17 | 字符串的第 ii 位置: 18 | 19 | - 可以单独作为一位来翻译 20 | - 如果第 i - 1i−1 位和第 ii 位组成的数字在 1010 到 2525 之间,可以把这两位连起来翻译 21 | 22 | ![image-20220221004819514](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220221004819514.png) 23 | 24 | ```go 25 | func translateNum(num int) int { 26 | s := strconv.Itoa(num) 27 | if len(s) == 0 { 28 | return 0 29 | } 30 | dp := make([]int, len(s)) 31 | dp[0] = 1 32 | if len(s) == 1 { 33 | return 1 34 | } 35 | if s[0:2] <= "25" && s[0:2] >= "10" { 36 | dp[1] = 2 37 | } else { 38 | dp[1] = 1 39 | } 40 | 41 | for i := 2; i < len(s); i++ { 42 | pre := s[i-1 : i+1] 43 | if pre <= "25" && pre >= "10" { 44 | dp[i] = dp[i-1] + dp[i-2] 45 | } else { 46 | dp[i] = dp[i-1] 47 | } 48 | } 49 | return dp[len(s)-1] 50 | } 51 | ``` 52 | 53 | ## 优化 54 | 55 | 将空间压缩为 O(1) 56 | 57 | ```go 58 | func translateNum(num int) int { 59 | s := strconv.Itoa(num) 60 | if len(s) == 0 { 61 | return 0 62 | } 63 | a1, a2 := 1, 1 // dp[i-1]和dp[i-2] 64 | result := 1 65 | for i := 1; i < len(s); i++ { 66 | pre := s[i-1 : i+1] // 当前位和上一位组成的二位数字 67 | if pre <= "25" && pre >= "10" { 68 | result = a1 + a2 69 | } else { 70 | result = a1 71 | } 72 | a2 = a1 73 | a1 = result 74 | } 75 | return result 76 | } 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/136. 只出现一次的数字.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "136. 只出现一次的数字" 3 | date: 2022-03-30 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, ] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 136. 只出现一次的数字 12 | 13 | 给定一个**非空**整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 14 | 15 | **说明:** 16 | 17 | 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入: [2,2,1] 23 | 输出: 1 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入: [4,1,2,1,2] 30 | 输出: 4 31 | ``` 32 | 33 | ## 异或 34 | 35 | ![image-20220810144822263](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220810144822263.png) 36 | 37 | 所以把所有元素异或在一起,就是那个只出现过一次的数字啦 38 | 39 | ```go 40 | func singleNumber(nums []int) int { 41 | res := nums[0] 42 | for i := 1; i < len(nums); i++ { 43 | res ^= nums[i] 44 | } 45 | return res 46 | } 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/1546. 和为目标值且不重叠的非空子数组的最大数目.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1546. 和为目标值且不重叠的非空子数组的最大数目" 3 | date: 2022-02-24 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 数组, 贪心, 前缀和] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 1546. 和为目标值且不重叠的非空子数组的最大数目 12 | 13 | `mid` 14 | 15 | 给你一个数组 `nums` 和一个整数 `target` 。 16 | 17 | 请你返回 **非空不重叠** 子数组的最大数目,且每个子数组中数字和都为 `target` 。 18 | 19 | ``` 20 | 示例 1: 21 | 22 | 输入:nums = [1,1,1,1,1], target = 2 23 | 输出:2 24 | 解释:总共有 2 个不重叠子数组(加粗数字表示) [1,1,1,1,1] ,它们的和为目标值 2 25 | ``` 26 | 27 | ``` 28 | 示例 2: 29 | 30 | 输入:nums = [-1,3,5,1,4,2,-9], target = 6 31 | 输出:2 32 | 解释:总共有 3 个子数组和为 6 。 33 | ([5,1], [4,2], [3,5,1,4,2,-9]) 但只有前 2 个是不重叠的。 34 | ``` 35 | 36 | ## 贪心 + 前缀和 37 | 38 | 贪心:由于题目要求所有的子数组**互不重叠**,因此对于某个满足条件的子数组,如果其右端点是所有满足条件的子数组的右端点中最小的那一个,则该子数组一定会被选择。 39 | 40 | 前缀和见 560 题 41 | 42 | ```go 43 | // 贪心 + 前缀和 44 | func maxNonOverlapping(nums []int, target int) int { 45 | count, curSum := 0, 0 46 | hash := map[int]int{0: 1} 47 | for i := 0; i < len(nums); i++ { 48 | curSum += nums[i] 49 | if hash[curSum-target] > 0 { 50 | count++ // 只记录一个 51 | // 清空前缀和记录 52 | hash = map[int]int{} 53 | curSum = 0 54 | } 55 | hash[curSum]++ 56 | } 57 | return count 58 | } 59 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/16. 最接近的三数之和.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "16. 最接近的三数之和" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | --- 9 | 10 | # 16. 最接近的三数之和 11 | 12 | `mid` 13 | 14 | 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。 15 | 16 | 返回这三个数的和。 17 | 18 | 假定每组输入只存在恰好一个解。 19 | 20 | ![image-20220227161358719](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220227161358719.png) 21 | 22 | ## 排序 + 对撞指针 23 | 24 | ```go 25 | func abs(x int) int { 26 | if x < 0 { 27 | return -x 28 | } 29 | return x 30 | } 31 | 32 | // 排序+双指针 33 | func threeSumClosest(nums []int, target int) int { 34 | sort.Ints(nums) 35 | minDiff := math.MaxInt32 36 | resultSum := math.MaxInt32 37 | for index := 1; index < len(nums)-1; index++ { 38 | start, end := 0, len(nums)-1 39 | for start < index && end > index { 40 | curSum := nums[start] + nums[index] + nums[end] 41 | curDiff := curSum - target 42 | 43 | if abs(curDiff) < minDiff { 44 | minDiff = abs(curDiff) 45 | resultSum = curSum 46 | } 47 | 48 | switch { 49 | case curDiff == 0: 50 | return resultSum 51 | case curDiff < 0: 52 | start++ 53 | default: 54 | end-- 55 | } 56 | } 57 | } 58 | return resultSum 59 | } 60 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/20. 有效的括号.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "20. 有效的括号" 3 | date: 2022-03-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 栈] 7 | categories: [刷题] 8 | --- 9 | 10 | # 20. 有效的括号 11 | 12 | `easy` 13 | 14 | 给定一个只包括 `'('`,`')'`,`'{'`,`'}'`,`'['`,`']'` 的字符串 `s` ,判断字符串是否有效。 15 | 16 | 有效字符串需满足: 17 | 18 | 1. 左括号必须用相同类型的右括号闭合。 19 | 2. 左括号必须以正确的顺序闭合。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:s = "()" 25 | 输出:true 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:s = "()[]{}" 32 | 输出:true 33 | ``` 34 | 35 | **示例 3:** 36 | 37 | ``` 38 | 输入:s = "(]" 39 | 输出:false 40 | ``` 41 | 42 | **示例 4:** 43 | 44 | ``` 45 | 输入:s = "([)]" 46 | 输出:false 47 | ``` 48 | 49 | **示例 5:** 50 | 51 | ``` 52 | 输入:s = "{[]}" 53 | 输出:true 54 | ``` 55 | 56 | ## 辅助栈 57 | 58 | ![image-20220320144513399](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220320144513399.png) 59 | 60 | ```go 61 | func isValid(s string) bool { 62 | quoteMap := map[byte]byte{ 63 | '(': ')', 64 | '[': ']', 65 | '{': '}', 66 | } 67 | stack := make([]byte, 0) 68 | for _, quote := range []byte(s) { 69 | switch quote { 70 | case ')', ']', '}': 71 | if len(stack) == 0 { 72 | return false 73 | } 74 | if quote != quoteMap[stack[len(stack)-1]] { 75 | return false 76 | } 77 | stack = stack[:len(stack)-1] 78 | default: 79 | stack = append(stack, quote) 80 | } 81 | } 82 | return len(stack) == 0 83 | } 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/209. 长度最小的子数组.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "209. 长度最小的子数组" 3 | date: 2022-02-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,滑动窗口] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 209. 长度最小的子数组 12 | 13 | `mid` 14 | 15 | 给定一个含有 `n` 个正整数的数组和一个正整数 `target` 16 | 17 | 找出该数组中满足其和 `≥ target` 的长度最小的 **连续子数组** `[numsl, numsl+1, ..., numsr-1, numsr]`,并返回其长度**。**如果不存在符合条件的子数组,返回 `0` 。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:target = 7, nums = [2,3,1,2,4,3] 23 | 输出:2 24 | 解释:子数组 [4,3] 是该条件下的长度最小的子数组。 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:target = 4, nums = [1,4,4] 31 | 输出:1 32 | ``` 33 | 34 | **示例 3:** 35 | 36 | ``` 37 | 输入:target = 11, nums = [1,1,1,1,1,1,1,1] 38 | 输出:0 39 | ``` 40 | 41 | ## 滑动窗口 42 | 43 | ```go 44 | func minSubArrayLen(target int, nums []int) int { 45 | i, j := 0, 0 46 | minLen := math.MaxInt 47 | var curSum int 48 | for j < len(nums) { 49 | curSum += nums[j] // 加上新边界 50 | for curSum >= target { 51 | if j-i+1 < minLen { 52 | minLen = j - i + 1 53 | } 54 | curSum -= nums[i] // 减去旧的左边界 55 | i++ 56 | } 57 | j++ 58 | 59 | } 60 | 61 | if minLen == math.MaxInt { 62 | return 0 63 | } 64 | return minLen 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/238. 除自身以外数组的乘积.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "560. 和为 K 的子数组" 3 | date: 2022-08-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 238. 除自身以外数组的乘积 12 | 13 | `mid` 14 | 15 | 给你一个整数数组 `nums`,返回 *数组 `answer` ,其中 `answer[i]` 等于 `nums` 中除 `nums[i]` 之外其余各元素的乘积* 。 16 | 17 | 题目数据 **保证** 数组 `nums`之中任意元素的全部前缀元素和后缀的乘积都在 **32 位** 整数范围内。 18 | 19 | 请**不要使用除法,**且在 `O(n)` 时间复杂度内完成此题。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入: nums = [1,2,3,4] 25 | 输出: [24,12,8,6] 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入: nums = [-1,1,0,-3,3] 32 | 输出: [0,0,9,0,0] 33 | ``` 34 | 35 | ## 左右乘积列表 36 | 37 | 乘积 = 当前数左边的乘积 * 当前数右边的乘积 38 | 39 | ```go 40 | func productExceptSelf(nums []int) []int { 41 | l, r, res := make([]int, len(nums)), make([]int, len(nums)), make([]int, len(nums)) 42 | // l[i]为i左边元素的乘积 43 | // r[i]为i右边元素的乘积 44 | l[0] = 1 45 | for i := 1; i < len(nums); i++ { 46 | l[i] = l[i-1] * nums[i-1] 47 | } 48 | r[len(nums)-1] = 1 49 | for i := len(nums) - 2; i >= 0; i--{ 50 | r[i] = r[i+1] * nums[i+1] 51 | } 52 | 53 | for i := 0; i < len(nums); i++ { 54 | res[i] = l[i] * r[i] 55 | } 56 | return res 57 | } 58 | ``` 59 | 60 | ## O(1) 空间解决 61 | 62 | 用 res 数组来暂时替代 l 数组,在复制的过程中,动态地修改 r[i] 的值(用一个临时变量 r 来表示) 63 | 64 | ```go 65 | func productExceptSelf(nums []int) []int { 66 | res := make([]int, len(nums)) 67 | // res[i]暂时为i左边元素的乘积 68 | res[0] = 1 69 | for i := 1; i < len(nums); i++ { 70 | res[i] = res[i-1] * nums[i-1] 71 | } 72 | 73 | r := 1 // i右侧元素乘积 74 | for i := len(nums) - 1; i >= 0; i-- { 75 | res[i] = res[i] * r 76 | r *= nums[i] 77 | } 78 | return res 79 | } 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/26. 删除有序数组中的重复项.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "26. 删除有序数组中的重复项" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | --- 9 | 10 | # 26. 删除有序数组中的重复项 11 | 12 | `easy` 13 | 14 | 给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。 15 | 16 | 不要使用额外的数组空间,你必须在原地修改输入数组 并在使用 O(1) 额外空间的条件下完成。 17 | 18 | ![image-20220227162041412](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220227162041412.png) 19 | 20 | ## 原地删除 21 | 22 | `append` 函数看起来蛮耗时的。。。 23 | 24 | ```go 25 | // removeDuplicates 比较蠢的 一次遍历 26 | func removeDuplicates(nums []int) int { 27 | dupLen := 0 28 | oriLen := len(nums) 29 | for i := 0; i < len(nums)-1; { 30 | if nums[i] == nums[i+1] { 31 | nums = append(nums[:i+1], nums[i+2:]...) // 删除 i+1 32 | dupLen++ 33 | // 此处不执行 i++ 34 | } else { 35 | i++ 36 | } 37 | 38 | } 39 | return oriLen - dupLen 40 | } 41 | ``` 42 | 43 | ## 双指针(重复元素后移) 44 | 45 | 一个指针 `i` 进行数组遍历,另外一个指针 `j` 指向**有效数组**的最后一个位置。 46 | 47 | ```go 48 | // removeDuplicates 把重复的元素移到最后面 (其实是覆盖掉) 49 | func removeDuplicates(nums []int) int { 50 | if len(nums) == 0 { 51 | return 0 52 | } 53 | i, j := 0, 0 54 | for i < len(nums)-1 { 55 | for nums[j] == nums[i] { 56 | // 右移j至与i不同处 57 | j++ 58 | if j == len(nums) { 59 | return i + 1 60 | } 61 | } 62 | nums[i+1] = nums[j] // 覆盖 跟替换一个意思 63 | i++ 64 | } 65 | return i + 1 66 | } 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/27. 移除元素.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "27. 移除元素" 3 | date: 2022-02-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 数组, 双指针] 7 | categories: [刷题] 8 | --- 9 | 10 | # 27. 移除元素 11 | 12 | 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 13 | 14 | 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 15 | 16 | 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 17 | 18 | ## 双指针 19 | 20 | **快慢指针**,j 遍历,i 等 j 匹配到与 val 不同的元素后与 j 交换,然后右移;这样可以保证 i 之前的所有元素都不是 val 21 | 22 | ```go 23 | // removeDuplicates 将重复元素与当前指针交换 24 | func removeElement(nums []int, val int) int { 25 | if len(nums) == 0 { 26 | return 0 27 | } 28 | i := 0 29 | for j := 0; j < len(nums); j++ { 30 | if nums[j] != val { 31 | nums[j], nums[i] = nums[i], nums[j] 32 | i++ 33 | } 34 | } 35 | return i 36 | } 37 | ``` 38 | 39 | **头尾指针**,一个道理 40 | 41 | ```go 42 | 43 | func removeElement(nums []int, val int) int { 44 | if len(nums) == 0 { 45 | return 0 46 | } 47 | l,r:=0,len(nums)-1 48 | for l<=r{ 49 | if nums[l]==val{ 50 | nums[l],nums[r]=nums[r],nums[l] 51 | r-- 52 | }else{ 53 | l++ 54 | } 55 | } 56 | return r+1 57 | } 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/283. 移动零.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "283. 移动零" 3 | date: 2022-03-04 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 283. 移动零 12 | 13 | `easy` 14 | 15 | 给定一个数组 `nums`,编写一个函数将所有 `0` 移动到数组的末尾,同时保持非零元素的相对顺序。 16 | 17 | **请注意** ,必须在不复制数组的情况下原地对数组进行操作。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入: nums = [0,1,0,3,12] 23 | 输出: [1,3,12,0,0] 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入: nums = [0] 30 | 输出: [0] 31 | ``` 32 | 33 | ## 快慢指针 34 | 35 | 不多 bb 36 | 37 | ```go 38 | func moveZeroes(nums []int) { 39 | var i, j = 0, 0 40 | for j < len(nums) { 41 | for nums[j] == 0 { 42 | // j移动到第一个非零位置 43 | j++ 44 | if j == len(nums) { 45 | return 46 | } 47 | } 48 | nums[i], nums[j] = nums[j], nums[i] 49 | i++ 50 | j++ 51 | } 52 | } 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/31. 下一个排列.md: -------------------------------------------------------------------------------- 1 | # 31. 下一个排列 2 | 3 | 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 4 | 5 | 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 6 | 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。 7 | 8 | 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。 9 | 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。 10 | 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。 11 | 给你一个整数数组 nums ,找出 nums 的下一个排列。 12 | 13 | 必须 原地 修改,只允许使用额外常数空间。 14 | 15 | ## 解 16 | 17 | 其实就是从数组**倒着查找**,找到 `nums[i]` 比 `nums[i+1]` 小的时候,就将 `nums[i]` 跟 `nums[i+1]` 到`nums[len(nums) - 1]` 当中找到一个最小的比 `nums[i]` 大的元素交换。交换后,再把 `nums[i+1]` 到 `nums[len(nums) - 1]` 排序,就 ok 了 18 | 19 | ```go 20 | func nextPermutation(nums []int) { 21 | i, j := 0, 0 22 | for i = len(nums) - 2; i >= 0; i-- { 23 | if nums[i] < nums[i+1] { 24 | break 25 | } 26 | } 27 | if i >= 0 { 28 | for j = len(nums) - 1; j > i; j-- { 29 | if nums[j] > nums[i] { 30 | break 31 | } 32 | } 33 | swap(&nums, i, j) 34 | } 35 | reverse(&nums, i+1, len(nums)-1) 36 | } 37 | 38 | func reverse(nums *[]int, i, j int) { 39 | for i < j { 40 | swap(nums, i, j) 41 | i++ 42 | j-- 43 | } 44 | } 45 | 46 | func swap(nums *[]int, i, j int) { 47 | (*nums)[i], (*nums)[j] = (*nums)[j], (*nums)[i] 48 | } 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/33. 搜索旋转排序数组.md: -------------------------------------------------------------------------------- 1 | # 搜索旋转排序数组 2 | 3 | `binary search` 4 | 5 | 整数数组 nums 按升序排列,数组中的值 互不相同 。 6 | 7 | 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。 8 | 9 | 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。 10 | 11 | ## 二分 12 | 13 | 如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在这一区域内,这样就可以确定保留哪半边了 14 | 15 | ```go 16 | // 二分法 17 | func search(nums []int, target int) int { 18 | if len(nums) == 0 { 19 | return -1 20 | } 21 | low, high := 0, len(nums)-1 22 | for low <= high { 23 | // 开始二分 24 | mid := low + (high-low)>>1 25 | if nums[mid] == target { 26 | return mid 27 | } else if nums[mid] > nums[high] { 28 | // 中间值大于右边值 左边必然有序 29 | if nums[low] <= target && target < nums[mid] { 30 | // 落在左边部分 31 | high = mid - 1 32 | } else { 33 | low = mid + 1 34 | } 35 | } else { 36 | // 中间值小于右边值 右边必然有序 37 | if nums[mid] < target && target <= nums[high] { 38 | // 落在右边部分 39 | low = mid + 1 40 | } else { 41 | high = mid - 1 42 | } 43 | } 44 | } 45 | return -1 46 | } 47 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/349. 两个数组的交集.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "349. 两个数组的交集" 3 | date: 2022-03-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组, 哈希] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 349. 两个数组的交集 12 | 13 | 给定两个数组 `nums1` 和 `nums2` ,返回 *它们的交集* 。输出结果中的每个元素一定是 **唯一** 的。我们可以 **不考虑输出结果的顺序** 。 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:nums1 = [1,2,2,1], nums2 = [2,2] 19 | 输出:[2] 20 | ``` 21 | 22 | **示例 2:** 23 | 24 | ```x 25 | 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 26 | 输出:[9,4] 27 | 解释:[4,9] 也是可通过的 28 | ``` 29 | 30 | ## 哈希 31 | 32 | 注意去重 33 | 34 | ```go 35 | func intersection(nums1 []int, nums2 []int) (res []int) { 36 | hash := make(map[int]struct{}, 0) 37 | for i := 0; i < len(nums1); i++ { 38 | hash[nums1[i]] = struct{}{} 39 | } 40 | for i := 0; i < len(nums2); i++ { 41 | if _, ok := hash[nums2[i]]; ok { 42 | res = append(res, nums2[i]) 43 | delete(hash, nums2[i]) // 去重 44 | } 45 | } 46 | return 47 | } 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/367. 有效的完全平方数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "367. 有效的完全平方数" 3 | date: 2022-03-04 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,二分] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 367. 有效的完全平方数 12 | 13 | `easy` 14 | 15 | 给定一个 **正整数** `num` ,编写一个函数,如果 `num` 是一个完全平方数,则返回 `true` ,否则返回 `false` 。 16 | 17 | **进阶:不要** 使用任何内置的库函数,如 `sqrt` 。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:num = 16 23 | 输出:true 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:num = 14 30 | 输出:false 31 | ``` 32 | 33 | ## 二分 34 | 35 | 不多 bb,跟 69 题差不多 36 | 37 | ```go 38 | func isPerfectSquare(num int) bool { 39 | low, high := 0, num 40 | for low <= high { 41 | mid := low + (high-low)>>1 42 | if mid*mid < num { 43 | low = mid + 1 44 | } else if mid*mid > num { 45 | high = mid - 1 46 | } else { 47 | return true 48 | } 49 | } 50 | return false 51 | } 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/560. 和为 K 的子数组.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "560. 和为 K 的子数组" 3 | date: 2022-02-24 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,前缀和] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 560. 和为 K 的子数组 12 | 13 | 给你一个整数数组 nums 和一个整数 k ,请你统计并返回该数组中和为 k 的连续子数组的个数。 14 | 15 | 示例 1: 16 | 17 | ``` 18 | 输入:nums = [1,1,1], k = 2 19 | 输出:2 20 | ``` 21 | 22 | 示例 2: 23 | 24 | ``` 25 | 输入:nums = [1,2,3], k = 3 26 | 输出:2 27 | ``` 28 | 29 | ## 前缀和 30 | 31 | > 前缀和:nums 的第 0 项到 当前项 的和。 32 | 33 | 定义 prefixSum 数组,prefixSum[x]:第 0 项到 第 x 项 的和。 34 | 35 | nums 的 第 i 到 j 项 的和,即为 `prefixSum[j] − prefixSum[i−1]` 36 | 37 | 当 i 为 0,此时 i-1 为 -1,我们**故意**让 prefixSum[-1] 为 0,使得通式在 `i=0` 时也成立 38 | 39 | ```go 40 | // 前缀和 41 | func subarraySum(nums []int, k int) int { 42 | count := 0 43 | curSum := 0 // 记录每次循环当前的前缀和 44 | hash := map[int]int{ 45 | 0: 1, // 前缀和为0 出现过1次了 46 | } 47 | for i := 0; i < len(nums); i++ { 48 | curSum += nums[i] 49 | if hash[curSum-k] > 0 { 50 | // 当前前缀和减去k的结果也在之前的前缀和表中 代表找到一个和为k的连续子数组 51 | count += hash[curSum-k] 52 | } 53 | hash[curSum]++ // 记录一个前缀和 54 | } 55 | return count 56 | } 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/69. x 的平方根 .md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "69. x 的平方根" 3 | date: 2022-03-04 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,二分] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 69. x 的 平方根 12 | 13 | `easy` 14 | 15 | 给你一个非负整数 `x` ,计算并返回 `x` 的 **算术平方根** 。 16 | 17 | 由于返回类型是整数,结果只保留 **整数部分** ,小数部分将被 **舍去 。** 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:x = 4 23 | 输出:2 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:x = 8 30 | 输出:2 31 | 解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。 32 | ``` 33 | 34 | ## 二分法 35 | 36 | x 平方根的整数部分 ans 是满足 k^2^ ≤ x 37 | 的最大 kk 值 38 | 39 | 不多 bb 40 | 41 | ```go 42 | func mySqrt(x int) int { 43 | low, high := 0, x 44 | for low <= high { 45 | mid := low + (high-low)>>1 46 | if mid*mid < x { 47 | if (mid+1)*(mid+1) > x { 48 | // 找到最后一个小于x的mid 49 | return mid 50 | } 51 | low = mid + 1 52 | } else if mid*mid > x { 53 | high = mid - 1 54 | } else { 55 | return mid 56 | } 57 | } 58 | return -1 59 | } 60 | ``` 61 | 62 | ![image-20220304091028914](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220304091028914.png) 63 | 64 | ## 袖珍计算器算法 65 | 66 | ![image-20220304090854893](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220304090854893.png) 67 | 68 | ![image-20220304090908600](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220304090908600.png) 69 | 70 | ```go 71 | func mySqrt(x int) int { 72 | if x == 0 { 73 | return 0 74 | } 75 | ans := int(math.Exp(0.5 * math.Log(float64(x)))) 76 | if (ans + 1) * (ans + 1) <= x { 77 | return ans + 1 78 | } 79 | return ans 80 | } 81 | ``` 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/977. 有序数组的平方.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "977. 有序数组的平方" 3 | date: 2022-03-04 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 977. 有序数组的平方 12 | 13 | `easy` 14 | 15 | 给你一个按 **非递减顺序** 排序的整数数组 `nums`,返回 **每个数字的平方** 组成的新数组,要求也按 **非递减顺序** 排序。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:nums = [-4,-1,0,3,10] 21 | 输出:[0,1,9,16,100] 22 | 解释:平方后,数组变为 [16,1,0,9,100] 23 | 排序后,数组变为 [0,1,9,16,100] 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:nums = [-7,-3,2,3,11] 30 | 输出:[4,9,9,49,121] 31 | ``` 32 | 33 | ## 归并 34 | 35 | 实际上是合并两个有序数组的题目 36 | 37 | ```go 38 | func sortedSquares(nums []int) []int { 39 | ans := make([]int, len(nums)) 40 | i := len(ans) - 1 41 | l, r := 0, len(nums)-1 42 | for l <= r { 43 | if nums[l]*nums[l] >= nums[r]*nums[r] { 44 | ans[i] = nums[l] * nums[l] 45 | l++ 46 | } else { 47 | ans[i] = nums[r] * nums[r] 48 | r-- 49 | } 50 | i-- 51 | } 52 | return ans 53 | } 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/双指针/11. 盛最多水的容器.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "11. 盛最多水的容器" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 11. 盛最多水的容器 12 | 13 | `mid` 14 | 15 | 给出一个非负整数数组 a~1~,a~2~,a~3~,…… a~n~,每个整数标识一个竖立在坐标轴 x 位置的一堵高度为 a~i~ 的墙,选择两堵墙,和 x 轴构成的容器可以容纳最多的水。 16 | 17 | ![image-20220227155740486](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220227155740486.png) 18 | 19 | ## 对撞指针 20 | 21 | ```go 22 | func maxArea(height []int) int { 23 | start, end := 0, len(height) 24 | curResult, maxResult := 0, 0 25 | for start < end { 26 | curWidth := end - start 27 | curHeight := 0 28 | // 因为高度取矮者 矮的一边的指针就可以往中间移动 因为反过来的移法面积必定更小 29 | if height[start] < height[end] { 30 | curHeight = height[start] 31 | start++ 32 | } else { 33 | curHeight = height[end] 34 | end-- 35 | } 36 | 37 | curResult = curWidth * curHeight 38 | if curResult > maxResult { 39 | maxResult = curResult 40 | } 41 | } 42 | return maxResult 43 | } 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/双指针/15. 三数之和.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "15. 三数之和" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 15. 三数之和 12 | 13 | `mid` 14 | 15 | 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。 16 | 17 | 注意:答案中不可以包含重复的三元组。 18 | 19 | ![image-20220227160232830](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220227160232830.png) 20 | 21 | ## 排序 + 对撞指针 22 | 23 | `l` 和 `r` 双指针从头/尾向中间移动 24 | 25 | ```go 26 | func threeSum(nums []int) [][]int { 27 | if len(nums) < 3 { 28 | return [][]int{} 29 | } 30 | sort.Ints(nums) 31 | res := make([][]int, 0) 32 | 33 | for i := 0; i < len(nums)-2; i++ { 34 | a := nums[i] 35 | if a > 0 { 36 | break 37 | } 38 | if i > 0 && nums[i] == nums[i-1] { 39 | // 避免i重复 40 | continue 41 | } 42 | l, r := i+1, len(nums)-1 43 | for l < r { 44 | b, c := nums[l], nums[r] 45 | if a+b+c > 0 { 46 | r-- 47 | } else if a+b+c < 0 { 48 | l++ 49 | } else { 50 | res = append(res, []int{a, b, c}) 51 | // 避免l或r重复 52 | for l < r && nums[l] == b { 53 | l++ 54 | } 55 | for r > l && nums[r] == c { 56 | r-- 57 | } 58 | } 59 | } 60 | } 61 | return res 62 | } 63 | ``` 64 | 65 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/双指针/75. 颜色分类.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "75. 颜色分类" 3 | date: 2022-04-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,查找,双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 75. 颜色分类 12 | 13 | `mid` 14 | 15 | 给定一个包含红色、白色和蓝色、共 `n` 个元素的数组 `nums` ,**[原地](https://baike.baidu.com/item/原地算法)**对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 16 | 17 | 我们使用整数 `0`、 `1` 和 `2` 分别表示红色、白色和蓝色。 18 | 19 | 必须在不使用库的 sort 函数的情况下解决这个问题。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:nums = [2,0,2,1,1,0] 25 | 输出:[0,0,1,1,2,2] 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:nums = [2,0,1] 32 | 输出:[0,1,2] 33 | ``` 34 | 35 | ## 单指针 36 | 37 | 可以考虑对数组进行**两次遍历**。在第一次遍历中,我们将数组中所有的 0 交换到数组的头部。在第二次遍历中,我们将数组中所有的 1 交换到头部的 0 之后。此时,所有的 2 都出现在数组的尾部,这样我们就完成了排序。 38 | 39 | ```go 40 | // 单指针 41 | func sortColors(nums []int) { 42 | k := 0 43 | // 把所有0放到开头 44 | for i := 0; i < len(nums); i++ { 45 | if nums[i] == 0 { 46 | nums[i], nums[k] = nums[k], nums[i] 47 | k++ 48 | } 49 | } 50 | // 把所有1放到0后 51 | for i := k; i < len(nums); i++ { 52 | if nums[i] == 1 { 53 | nums[i], nums[k] = nums[k], nums[i] 54 | k++ 55 | } 56 | } 57 | } 58 | ``` 59 | 60 | ## 双指针 61 | 62 | 使用两个指针分别用来交换 0 和 1,只要遍历一次就好啦 63 | 64 | 注意 `p0 < p1` 的情况,会把 1 换走,这时候要把这个 1 换到 p1 上 65 | 66 | ```go 67 | // 双指针 68 | func sortColors(nums []int) { 69 | p0, p1 := 0, 0 70 | for i, num := range nums { 71 | if num == 0 { 72 | nums[i], nums[p0] = nums[p0], nums[i] 73 | if p0 < p1 { 74 | nums[i], nums[p1] = nums[p1], nums[i] 75 | } 76 | p0++ 77 | p1++ 78 | } else if num == 1 { 79 | nums[i], nums[p1] = nums[p1], nums[i] 80 | p1++ 81 | } 82 | } 83 | } 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/双指针/剑指 Offer 21. 调整数组顺序使奇数位于偶数前面.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 21. 调整数组顺序使奇数位于偶数前面" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 双指针, 快慢指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 12 | 13 | `easy` 14 | 15 | 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。 16 | 17 | **示例:** 18 | 19 | ``` 20 | 输入:nums = [1,2,3,4] 21 | 输出:[1,3,2,4] 22 | 注:[3,1,2,4] 也是正确的答案之一。 23 | ``` 24 | 25 | 相当标准的双指针题目 26 | 27 | ## 快慢指针 28 | 29 | ```go 30 | func exchange(nums []int) []int { 31 | // slow 始终在第一个偶数上,fast 往前探索找奇数 32 | slow, fast := 0, 0 33 | for fast < len(nums) { 34 | if nums[fast]%2 == 1 { 35 | // 是奇数 36 | nums[slow], nums[fast] = nums[fast], nums[slow] 37 | slow++ 38 | } 39 | fast++ 40 | } 41 | return nums 42 | } 43 | ``` 44 | 45 | ## 头尾指针 46 | 47 | ```go 48 | func exchange(nums []int) []int { 49 | low, high := 0, len(nums)-1 50 | 51 | for low <= high { 52 | for low < len(nums) && nums[low]%2 == 1 { 53 | // low 往前走 直到遇到偶数 54 | low++ 55 | } 56 | for high >= 0 && nums[high]%2 == 0 { 57 | // high 往后退 直到遇到奇数 58 | high-- 59 | } 60 | if low < high { 61 | nums[low], nums[high] = nums[high], nums[low] 62 | } 63 | } 64 | return nums 65 | } 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/双指针/剑指 Offer 57. 和为 s 的两个数字.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 57. 和为 s 的两个数字" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 57. 和为 s 的两个数字 12 | 13 | `easy` 14 | 15 | 输入一个递增排序的数组和一个数字 s,在数组中查找两个数,使得它们的和正好是 s。 16 | 17 | 如果有多对数字的和等于 s,则输出任意一对即可。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:nums = [2,7,11,15], target = 9 23 | 输出:[2,7] 或者 [7,2] 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:nums = [10,26,30,31,47,60], target = 40 30 | 输出:[10,30] 或者 [30,10] 31 | ``` 32 | 33 | ## 对撞指针 34 | 35 | 头尾指针:和小了,左指针右移;和大了,右指针左移 36 | 37 | ```go 38 | func twoSum(nums []int, target int) []int { 39 | if len(nums) <= 1 { 40 | return []int{} 41 | } 42 | i, j := 0, len(nums)-1 43 | for i < j { 44 | if nums[i]+nums[j] < target { 45 | i++ 46 | } else if nums[i]+nums[j] > target { 47 | j-- 48 | } else { 49 | return []int{nums[i], nums[j]} 50 | } 51 | } 52 | return []int{} 53 | } 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/哈希/1. 两数之和.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1. 两数之和" 3 | date: 2022-01-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 1. 两数之和 12 | 13 | `easy` 14 | 15 | 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。 16 | 17 | 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 18 | 19 | 你可以按任意顺序返回答案。 20 | 21 | ## 两重循环 22 | 23 | 时间复杂度 O(n^2^),空间复杂度 O(1) 24 | 25 | ```python 26 | class Solution: 27 | def twoSum(self, nums: List[int], target: int) -> List[int]: 28 | for i in range(len(nums)): 29 | for j in range(i+1,len(nums)): 30 | if nums[i] +nums[j]==target: 31 | return [i,j] 32 | ``` 33 | 34 | ```go 35 | func twoSum(nums []int, target int) []int { 36 | for i,num1:=range nums{ 37 | for j,num2:=range nums[i+1:]{ 38 | if num1+num2==target{ 39 | return []int{i,j+i+1} 40 | } 41 | } 42 | } 43 | return nil 44 | } 45 | ``` 46 | 47 | ## 哈希表 48 | 49 | 键为数组中各元素的值,哈希表的值为数组中该值出现的位置 50 | 51 | 在哈希表中是否存在 `target - nums[i]` 的键,若存在则说明这两数相加结果为 target,返回结果。 52 | 53 | ```python 54 | class Solution: 55 | def twoSum(self, nums: List[int], target: int) -> List[int]: 56 | d={} 57 | for i,num in enumerate(nums): 58 | if target-num in d.keys(): 59 | return [i,d[target-num]] 60 | d[num]=i 61 | ``` 62 | 63 | ```go 64 | func twoSum(nums []int, target int) []int { 65 | prevNums := map[int]int{} 66 | for i, num1 := range nums { 67 | num2 := target - num1 68 | j, ok := prevNums[num2] 69 | if ok { 70 | return []int{j, i} 71 | } else { 72 | prevNums[num1] = i 73 | } 74 | } 75 | return []int{} 76 | } 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/哈希/454. 四数相加 II.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "454. 四数相加 II" 3 | date: 2022-03-08 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 哈希] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 454. 四数相加 II 12 | 13 | `mid` `哈希` 14 | 15 | 给你四个整数数组 `nums1`、`nums2`、`nums3` 和 `nums4` ,数组长度都是 `n` ,请你计算有多少个元组 `(i, j, k, l)` 能满足: 16 | 17 | - `0 <= i, j, k, l < n` 18 | - `nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0` 19 | 20 | **示例 1:** 21 | 22 | ``` 23 | 输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 24 | 输出:2 25 | 解释: 26 | 两个元组如下: 27 | 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 28 | 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0 29 | ``` 30 | 31 | **示例 2:** 32 | 33 | ``` 34 | 输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0] 35 | 输出:1 36 | ``` 37 | 38 | ## 分组 + 哈希 39 | 40 | 时间复杂度:$O(n^2)$ 41 | 42 | 找到所有 a+b 的和,跟 c+d 的和匹配;注意可以重复 43 | 44 | ```go 45 | func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int { 46 | hash := make(map[int]int) 47 | count := 0 48 | for _, a := range nums1 { 49 | for _, b := range nums2 { 50 | hash[a+b]++ 51 | } 52 | } 53 | for _, c := range nums3 { 54 | for _, d := range nums4 { 55 | count += hash[-(c + d)] 56 | } 57 | } 58 | return count 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/排序/56. 合并区间.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "56. 合并区间" 3 | date: 2022-07-02 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 56. 合并区间 12 | 13 | `easy` 14 | 15 | 以数组 `intervals` 表示若干个区间的集合,其中单个区间为 `intervals[i] = [starti, endi]` 。请你合并所有重叠的区间,并返回 *一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间* 。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 21 | 输出:[[1,6],[8,10],[15,18]] 22 | 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:intervals = [[1,4],[4,5]] 29 | 输出:[[1,5]] 30 | 解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。 31 | ``` 32 | 33 | ## 排序 34 | 35 | 按左边界升序排序 36 | 37 | ![56-2.png](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/50417462969bd13230276c0847726c0909873d22135775ef4022e806475d763e-56-2.png) 38 | 39 | 我们用数组 res 存储最终的答案。 40 | 41 | 首先,我们将列表中的区间按照左端点升序排序。然后我们将第一个区间加入 res 数组中,并按顺序依次考虑之后的每个区间: 42 | 43 | - 如果当前区间的**左端点**比 res 中最后一个区间的**右端点**大,那么它们不会重合,我们可以直接将这个区间加入 res 的末尾; 44 | 45 | - 否则,它们重合,我们需要用当前区间的右端点更新数组 res 中最后一个区间的右端点,将其置为二者的较大值。 46 | 47 | ```go 48 | import "sort" 49 | 50 | func max(a, b int) int { 51 | if a > b { 52 | return a 53 | } 54 | return b 55 | } 56 | 57 | func merge(intervals [][]int) [][]int { 58 | sort.Slice(intervals, func(i, j int) bool { return intervals[i][0] < intervals[j][0] }) 59 | res := make([][]int, 0) 60 | for _, interval := range intervals { 61 | // res最后一个区间的右边界与interval的左边界比 62 | if len(res) == 0 || res[len(res)-1][1] < interval[0] { 63 | res = append(res, interval) 64 | } else { 65 | // 有重合 66 | res[len(res)-1][1] = max(res[len(res)-1][1], interval[1]) 67 | } 68 | } 69 | return res 70 | } 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/查找/169. 多数元素.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "169. 多数元素" 3 | date: 2022-08-03 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 数组] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 169. 多数元素 12 | 13 | `easy` 14 | 15 | 给定一个大小为 `n` 的数组 `nums` ,返回其中的多数元素。多数元素是指在数组中出现次数 **大于** `⌊ n/2 ⌋` 的元素。 16 | 17 | 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:nums = [2,2,1,1,1,2,2] 23 | 输出:2 24 | ``` 25 | 26 | ## 排序 + 取中间数 27 | 28 | 排序,取中间数,必是多数元素 29 | 30 | image.png 31 | 32 | ```go 33 | func majorityElement(nums []int) int { 34 | sort.Ints(nums) 35 | midVal := nums[(0+len(nums)-1)>>1] 36 | return midVal 37 | } 38 | ``` 39 | 40 | ## 摩尔投票 41 | 42 | 两两对拼消耗 43 | 44 | ```go 45 | func majorityElement(nums []int) int { 46 | targetNum, count := nums[0], 1 47 | for i := 1; i < len(nums); i++ { 48 | if nums[i] == targetNum { 49 | count++ 50 | } else { 51 | count-- 52 | } 53 | if count == -1 { 54 | targetNum, count = nums[i], 1 55 | } 56 | } 57 | return targetNum 58 | } 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/查找/35. 搜索插入位置.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "35. 搜索插入位置" 3 | date: 2022-03-05 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 数组, 二分] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 35. 搜索插入位置 12 | 13 | `easy` `二分` 14 | 15 | 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 16 | 17 | 请必须使用时间复杂度为 O(log n) 的算法。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入: nums = [1,3,5,6], target = 5 23 | 输出: 2 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入: nums = [1,3,5,6], target = 2 30 | 输出: 1 31 | ``` 32 | 33 | **示例 3:** 34 | 35 | ``` 36 | 输入: nums = [1,3,5,6], target = 7 37 | 输出: 4 38 | ``` 39 | 40 | - `nums` 为**无重复元素**的**升序**排列数组 41 | 42 | ## 二分 43 | 44 | 经典的二分搜索的变种题 45 | 46 | ```go 47 | // searchInsert 找到第一个比target大的 或者找到最后一个比target小的元素即可 48 | func searchInsert(nums []int, target int) int { 49 | low, high := 0, len(nums)-1 50 | for low <= high { 51 | mid := (low + high) >> 1 52 | if target < nums[mid] { 53 | if mid == 0 || target > nums[mid-1] { 54 | return mid 55 | } 56 | high = mid - 1 57 | } else if target > nums[mid] { 58 | if mid == len(nums)-1 || target < nums[mid+1] { 59 | return mid + 1 60 | } 61 | low = mid + 1 62 | } else { 63 | return mid 64 | } 65 | } 66 | return -1 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/查找/剑指 Offer 11. 旋转数组的最小数字.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 11. 旋转数组的最小数字" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,二分] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 11. 旋转数组的最小数字 12 | 13 | `easy` `二分` 14 | 15 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 16 | 17 | 给你一个可能存在**重复**元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为 1。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:[3,4,5,1,2] 23 | 输出:1 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:[2,2,2,0,1] 30 | 输出:0 31 | ``` 32 | 33 | ## 分析 34 | 35 | 首先,遍历一定是可以的。。但是时间复杂度是 O(N) 36 | 37 | ## 二分 38 | 39 | - middle > high:代表最小值一定在 middle 右侧,所以 low 移到 middle + 1 的位置。 40 | - middle < high:代表最小值一定在 middle 左侧**或者就是 middle**,所以 high 移到 middle 的位置。 41 | - middle == high:这时候不好判断,只能**让 high 指针递减**,来一个一个找最小值了。 42 | 43 | ```go 44 | // 二分 45 | func minArray2(numbers []int) int { 46 | low := 0 47 | high := len(numbers) - 1 48 | for low < high { 49 | mid := low + (high-low)/2 50 | if numbers[mid] < numbers[high] { 51 | high = mid 52 | } else if numbers[mid] > numbers[high] { 53 | low = mid + 1 54 | } else { 55 | high-- 56 | } 57 | } 58 | return numbers[low] 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/查找/剑指 Offer 53 - I. 在排序数组中查找数字 I.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 53 - I. 在排序数组中查找数字 I" 3 | date: 2022-02-22 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,查找,二分] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 53 - I. 在排序数组中查找数字 I 12 | 13 | `easy` `二分` 14 | 15 | 统计一个数字在排序数组中出现的次数。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入: nums = [5,7,7,8,8,10], target = 8 21 | 输出: 2 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入: nums = [5,7,7,8,8,10], target = 6 28 | 输出: 0 29 | ``` 30 | 31 | ## 二分 32 | 33 | 跟 34 题差不多 34 | 35 | ```go 36 | func search(nums []int, target int) int { 37 | low, high := 0, len(nums)-1 38 | for low <= high { 39 | mid := (high + low) >> 1 40 | if nums[mid] > target { 41 | high = mid - 1 42 | } else if nums[mid] < target { 43 | low = mid + 1 44 | } else { 45 | count := 1 46 | i := mid 47 | for i-1 >= 0 && nums[i] == nums[i-1] { 48 | count++ 49 | i-- 50 | } 51 | i = mid 52 | for i+1 <= len(nums)-1 && nums[i] == nums[i+1] { 53 | count++ 54 | i++ 55 | } 56 | return count 57 | } 58 | } 59 | return 0 60 | } 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/栈与队列/150. 逆波兰表达式求值.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "150. 逆波兰表达式求值" 3 | date: 2022-04-06 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数组,栈] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 150. 逆波兰表达式求值 12 | 13 | `mid` 14 | 15 | 根据[ 逆波兰表示法](https://baike.baidu.com/item/逆波兰式/128437),求表达式的值。 16 | 17 | 有效的算符包括 `+`、`-`、`*`、`/` 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 18 | 19 | **注意** 两个整数之间的除法只保留整数部分。 20 | 21 | 可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 22 | 23 | **示例 1:** 24 | 25 | ``` 26 | 输入:tokens = ["2","1","+","3","*"] 27 | 输出:9 28 | 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9 29 | ``` 30 | 31 | **示例 2:** 32 | 33 | ``` 34 | 输入:tokens = ["4","13","5","/","+"] 35 | 输出:6 36 | 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6 37 | ``` 38 | 39 | ## 栈 40 | 41 | 后缀表达式嘛,其实逆波兰表达式相当于是二叉树中的后序遍历 42 | 43 | ```go 44 | func evalRPN(tokens []string) int { 45 | stack := make([]int, 0) 46 | for i := 0; i < len(tokens); i++ { 47 | switch tokens[i] { 48 | case "+": 49 | a := stack[len(stack)-1] 50 | b := stack[len(stack)-2] 51 | stack = stack[:len(stack)-2] 52 | stack = append(stack, b+a) 53 | case "-": 54 | a := stack[len(stack)-1] 55 | b := stack[len(stack)-2] 56 | stack = stack[:len(stack)-2] 57 | stack = append(stack, b-a) 58 | case "*": 59 | a := stack[len(stack)-1] 60 | b := stack[len(stack)-2] 61 | stack = stack[:len(stack)-2] 62 | stack = append(stack, b*a) 63 | case "/": 64 | a := stack[len(stack)-1] 65 | b := stack[len(stack)-2] 66 | stack = stack[:len(stack)-2] 67 | stack = append(stack, b/a) 68 | default: 69 | num, _ := strconv.Atoi(tokens[i]) 70 | stack = append(stack, num) 71 | } 72 | } 73 | return stack[0] 74 | } 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/栈与队列/剑指 Offer 09. 用两个栈实现队列.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 09. 用两个栈实现队列" 3 | date: 2022-02-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,栈与队列] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 09. 用两个栈实现队列 12 | 13 | `easy` `stack` 14 | 15 | https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/ 16 | 17 | 用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 ) 18 | 19 | 示例 1: 20 | 21 | ``` 22 | 输入: 23 | ["CQueue","appendTail","deleteHead","deleteHead"] 24 | [[],[3],[],[]] 25 | 输出:[null,null,3,-1] 26 | ``` 27 | 28 | ## 双栈 29 | 30 | 根据栈先进后出的特性,我们每次往第一个栈里插入元素后,第一个栈的顶部元素是最后插入的元素,第一个栈的底部元素是下一个待删除的元素。 31 | 32 | 为了维护队列先进先出的特性,我们引入第二个栈,用第二个栈维护待删除的元素,在执行删除操作的时候我们首先看下第二个栈是否为空。 33 | 34 | 如果为空,我们将第一个栈里的元素一个个弹出插入到第二个栈里,这样第二个栈里元素的顺序就是待删除的元素的顺序,要执行删除操作的时候我们直接弹出第二个栈的元素返回即可。 35 | 36 | ```go 37 | type CQueue struct { 38 | stack1 []int // 主栈 39 | stack2 []int // 副栈 40 | } 41 | 42 | func Constructor() CQueue { 43 | return CQueue{stack1: []int{}, stack2: []int{}} 44 | } 45 | 46 | func (this *CQueue) AppendTail(value int) { 47 | this.stack1 = append(this.stack1, value) 48 | } 49 | 50 | func (this *CQueue) DeleteHead() int { 51 | // 只有stack2为空时,stack1中的元素才会倒入stack2中 52 | if len(this.stack2) == 0 { 53 | if len(this.stack1) == 0 { 54 | return -1 55 | } 56 | // 逆序传给stack2 57 | for i := len(this.stack1) - 1; i >= 0; i-- { 58 | this.stack2 = append(this.stack2, this.stack1[i]) 59 | } 60 | this.stack1 = []int{} 61 | } 62 | result := this.stack2[len(this.stack2)-1] 63 | this.stack2 = this.stack2[:len(this.stack2)-1] // 去掉stack2栈顶元素 64 | return result 65 | } 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/array/模拟/48. 旋转图像.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "48. 旋转图像" 3 | date: 2022-03-24 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,模拟] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 48. 旋转图像 12 | 13 | `mid` 14 | 15 | 给定一个 *n* × *n* 的二维矩阵 `matrix` 表示一个图像。请你将图像顺时针旋转 90 度。 16 | 17 | 你必须在**[ 原地](https://baike.baidu.com/item/原地算法)** 旋转图像,这意味着你需要直接修改输入的二维矩阵。**请不要** 使用另一个矩阵来旋转图像。 18 | 19 | **示例 1:** 20 | 21 | img 22 | 23 | ``` 24 | 输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 25 | 输出:[[7,4,1],[8,5,2],[9,6,3]] 26 | ``` 27 | 28 | ## 模拟 29 | 30 | 一层一层来,一个一个转 31 | 32 | 就这样吧 33 | 34 | ```go 35 | func rotate(matrix [][]int) { 36 | n := len(matrix) 37 | for layer := 0; layer < n/2; layer++ { 38 | end := n - 1 - layer 39 | for i := layer; i < end; i++ { 40 | a := matrix[layer][i] // 左上 41 | b := matrix[i][end] // 右上 42 | c := matrix[end][n-1-i] // 右下 43 | d := matrix[n-1-i][layer] // 左下 44 | 45 | matrix[layer][i] = d 46 | matrix[i][end] = a 47 | matrix[end][n-1-i] = b 48 | matrix[n-1-i][layer] = c 49 | } 50 | } 51 | } 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/2044. 统计按位或能得到最大值的子集数目.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "2044. 统计按位或能得到最大值的子集数目" 3 | date: 2022-03-15 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 回溯, DFS] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 2044. 统计按位或能得到最大值的子集数目 12 | 13 | 给你一个整数数组 `nums` ,请你找出 `nums` 子集 **按位或** 可能得到的 **最大值** ,并返回按位或能得到最大值的 **不同非空子集的数目** 14 | 15 | 如果数组 `a` 可以由数组 `b` 删除一些元素(或不删除)得到,则认为数组 `a` 是数组 `b` 的一个 **子集** 。如果选中的元素下标位置不一样,则认为两个子集 **不同** 。 16 | 17 | 对数组 `a` 执行 **按位或** ,结果等于 `a[0] OR a[1] OR ... OR a[a.length - 1]`(下标从 **0** 开始)。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:nums = [3,1] 23 | 输出:2 24 | 解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 : 25 | - [3] 26 | - [3,1] 27 | ``` 28 | 29 | **示例 2:** 30 | 31 | ``` 32 | 输入:nums = [2,2,2] 33 | 输出:7 34 | 解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。 35 | ``` 36 | 37 | ## DFS 38 | 39 | ```go 40 | func countMaxOrSubsets(nums []int) (ans int) { 41 | maxOr := 0 42 | var dfs func(int, int) 43 | dfs = func(pos, or int) { 44 | if pos == len(nums) { 45 | if or > maxOr { 46 | maxOr = or 47 | ans = 1 48 | } else if or == maxOr { 49 | ans++ 50 | } 51 | return 52 | } 53 | dfs(pos+1, or|nums[pos]) // 或 54 | dfs(pos+1, or) // 不或 55 | } 56 | dfs(0, 0) 57 | return 58 | } 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/216. 组合总和 III.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "216. 组合总和 III" 3 | date: 2022-07-15 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 回溯, 组合] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 216. 组合总和 III 12 | 13 | `mid` 14 | 15 | 找出所有相加之和为 `n` 的 `k` 个数的组合,且满足下列条件: 16 | 17 | - 只使用数字 1 到 9 18 | - 每个数字 **最多使用一次** 19 | 20 | 返回 *所有可能的有效组合的列表* 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。 21 | 22 | **示例 1:** 23 | 24 | ``` 25 | 输入: k = 3, n = 7 26 | 输出: [[1,2,4]] 27 | 解释: 28 | 1 + 2 + 4 = 7 29 | 没有其他符合的组合了。 30 | ``` 31 | 32 | **示例 2:** 33 | 34 | ``` 35 | 输入: k = 3, n = 9 36 | 输出: [[1,2,6], [1,3,5], [2,3,4]] 37 | 解释: 38 | 1 + 2 + 6 = 9 39 | 1 + 3 + 5 = 9 40 | 2 + 3 + 4 = 9 41 | 没有其他符合的组合了。 42 | ``` 43 | 44 | ## DFS 回溯 45 | 46 | 子集问题 47 | 48 | k 相当于树的深度,n 是树的宽度 49 | 50 | ![216.组合总和III](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/20201123195717975.png) 51 | 52 | ```go 53 | func combinationSum3(k int, n int) [][]int { 54 | // k: 层数 55 | var res=make([][]int,0) 56 | var tmp=make([]int,0) 57 | var dfs func(layer, sum, startIndex int) 58 | dfs = func(layer, sum, startIndex int){ 59 | if layer==k{ 60 | if sum==n{ 61 | res=append(res,append([]int{},tmp...)) 62 | } 63 | return 64 | } 65 | for i:=startIndex;i<=9;i++{ 66 | if sum+i>n{ 67 | // 小小剪个枝 68 | continue 69 | } 70 | tmp=append(tmp,i) 71 | dfs(layer+1,sum+i,i+1) 72 | tmp=tmp[:len(tmp)-1] 73 | } 74 | } 75 | dfs(0,0,1) 76 | return res 77 | } 78 | ``` 79 | 80 | > 回溯法中递归函数参数很难一次性确定下来,一般先写逻辑,需要啥参数了,填什么参数。 -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/39. 组合总和.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "39. 组合总和" 3 | date: 2022-03-24 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,回溯, 组合] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 39. 组合总和 12 | 13 | 给你一个 **无重复元素** 的整数数组 `candidates` 和一个目标整数 `target`,找出 `candidates` 中可以使数字和为目标数 `target` 的 *所有* **不同组合** ,并以列表形式返回。你可以按 **任意顺序** 返回这些组合。 14 | 15 | `candidates` 中的 **同一个** 数字可以 **无限制重复被选取** 。如果至少一个数字的被选数量不同,则两种组合是不同的。 16 | 17 | 对于给定的输入,保证和为 `target` 的不同组合数少于 `150` 个。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:candidates = [2,3,6,7], target = 7 23 | 输出:[[2,2,3],[7]] 24 | 解释: 25 | 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。 26 | 7 也是一个候选, 7 = 7 。 27 | 仅有这两种组合。 28 | ``` 29 | 30 | **示例 2:** 31 | 32 | ``` 33 | 输入: candidates = [2,3,5], target = 8 34 | 输出: [[2,2,2,2],[2,3,3],[3,5]] 35 | ``` 36 | 37 | **示例 3:** 38 | 39 | ``` 40 | 输入: candidates = [2], target = 1 41 | 输出: [] 42 | ``` 43 | 44 | ## DFS 回溯 45 | 46 | 注意到这是个**组合**问题,所以要用 `startIndex` 避免重复 47 | 48 | ```go 49 | func combinationSum(candidates []int, target int) [][]int { 50 | res := make([][]int, 0) 51 | comb := make([]int, 0) 52 | var dfs func(sum, startIndex int) 53 | dfs = func(sum, startIndex int) { 54 | if sum == target { 55 | combCopy := make([]int, len(comb)) 56 | copy(combCopy, comb) 57 | res = append(res, combCopy) 58 | return 59 | } 60 | if sum > target { 61 | return 62 | } 63 | for i := startIndex; i < len(candidates); i++ { 64 | comb = append(comb, candidates[i]) 65 | dfs(sum+candidates[i], i) 66 | comb = comb[:len(comb)-1] 67 | } 68 | } 69 | dfs(0, 0) 70 | return res 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/46. 全排列.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "46. 全排列" 3 | date: 2022-03-15 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 回溯, 排列] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # :star: 46. 全排列 12 | 13 | `mid` 14 | 15 | 给定一个不含重复数字的数组 `nums` ,返回其 *所有可能的全排列* 。你可以 **按任意顺序** 返回答案。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:nums = [1,2,3] 21 | 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入:nums = [0,1] 28 | 输出:[[0,1],[1,0]] 29 | ``` 30 | 31 | **示例 3:** 32 | 33 | ``` 34 | 输入:nums = [1] 35 | 输出:[[1]] 36 | ``` 37 | 38 | ## 全排列回溯 39 | 40 | 还原变量的思想值得好好学习 41 | 42 | ```go 43 | func permute(nums []int) [][]int { 44 | res := make([][]int, 0) 45 | var bt func(nums, path []int) 46 | bt = func(nums, path []int) { 47 | if len(nums) == 0 { 48 | p := make([]int, len(path)) 49 | copy(p, path) // 拷贝 50 | res = append(res, p) 51 | return 52 | } 53 | n := len(nums) 54 | for i := 0; i < n; i++ { 55 | cur := nums[i] 56 | 57 | path = append(path, cur) 58 | nums = append(nums[:i], nums[i+1:]...) 59 | bt(nums, path) 60 | // 还原 61 | nums = append(nums[:i], append([]int{cur}, nums[i:]...)...) 62 | path = path[:len(path)-1] 63 | } 64 | } 65 | bt(nums, []int{}) 66 | return res 67 | } 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/77. 组合.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "77. 组合" 3 | date: 2022-07-08 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 回溯, 组合] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 77. 组合 12 | 13 | `mid` 14 | 15 | 给定两个整数 `n` 和 `k`,返回范围 `[1, n]` 中所有可能的 `k` 个数的组合。 16 | 17 | 你可以按 **任何顺序** 返回答案。 18 | 19 | ## DFS 回溯 20 | 21 | n 中选 k 个,经典的**组合**问题 22 | 23 | ![image-20220708115434924](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220708115434924.png) 24 | 25 | 注意用 `startIndex` 避免重复 26 | 27 | ```go 28 | func combine(n int, k int) [][]int { 29 | res := make([][]int, 0) 30 | set := make([]int, 0) 31 | var dfs func(startIndex, layer int) 32 | dfs = func(startIndex, layer int) { 33 | if layer == k { 34 | res = append(res, append([]int{}, set...)) 35 | return 36 | } 37 | for i := startIndex; i < n; i++ { 38 | set = append(set, i+1) 39 | dfs(i+1, layer+1) 40 | set = set[:len(set)-1] 41 | } 42 | } 43 | dfs(0, 0) 44 | return res 45 | } 46 | ``` 47 | 48 | ### 剪枝 49 | 50 | 来个剪枝,帅的一 51 | 52 | 如果当前能够提供的元素数量小于还需要的元素数量,那就剪去 53 | 54 | ![image-20220708144016036](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220708144016036.png) 55 | 56 | ```go 57 | func combine(n int, k int) [][]int { 58 | res := make([][]int, 0) 59 | set := make([]int, 0) 60 | var dfs func(startIndex, layer int) 61 | dfs = func(startIndex, layer int) { 62 | if layer == k { 63 | res = append(res, append([]int{}, set...)) 64 | return 65 | } 66 | if n-startIndex < k-len(set) { 67 | // 剪枝 如果当前能够提供的元素数量小于还需要的元素数量 那就剪去 68 | return 69 | } 70 | for i := startIndex; i < n; i++ { 71 | set = append(set, i+1) 72 | dfs(i+1, layer+1) 73 | set = set[:len(set)-1] 74 | } 75 | } 76 | dfs(0, 0) 77 | return res 78 | } 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/90. 子集 II.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "90. 子集 II" 3 | date: 2022-07-08 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 回溯, 组合] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 90. 子集 II 12 | 13 | `mid` 14 | 15 | 给你一个整数数组 `nums` ,其中可能包含**重复元素**,请你返回该数组所有可能的子集(幂集)。 16 | 17 | 解集 **不能** 包含重复的子集。返回的解集中,子集可以按 **任意顺序** 排列。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:nums = [1,2,2] 23 | 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]] 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:nums = [0] 30 | 输出:[[],[0]] 31 | ``` 32 | 33 | ## DFS 回溯 34 | 35 | 组合问题,跟子集Ⅰ的不同是包含重复元素了,得去重(采用排序的方式),保证同一层上不能有重复的元素,不同层是可以重复的 36 | 37 | ![image-20220707203603709](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220707203603709.png) 38 | 39 | ```go 40 | import "sort" 41 | 42 | func subsetsWithDup(nums []int) [][]int { 43 | sort.Ints(nums) 44 | res := make([][]int, 0) 45 | subset := make([]int, 0) 46 | var dfs func(startIndex int) 47 | dfs = func(startIndex int) { 48 | res = append(res, append([]int{}, subset...)) 49 | for i := startIndex; i < len(nums); i++ { 50 | if i > startIndex && nums[i] == nums[i-1] { 51 | // 去重 52 | continue 53 | } 54 | subset = append(subset, nums[i]) 55 | dfs(i + 1) 56 | subset = subset[:len(subset)-1] 57 | } 58 | } 59 | dfs(0) 60 | return res 61 | } 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/DFS/17. 电话号码的字母组合.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "17. 电话号码的字母组合" 3 | date: 2022-03-14 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,回溯,排列] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 17. 电话号码的字母组合 12 | 13 | `mid` 14 | 15 | 给定一个仅包含数字 `2-9` 的字符串,返回所有它能表示的字母组合。答案可以按 **任意顺序** 返回。 16 | 17 | 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 18 | 19 | ![img](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2021/11/09/200px-telephone-keypad2svg.png) 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:digits = "23" 25 | 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"] 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:digits = "" 32 | 输出:[] 33 | ``` 34 | 35 | **示例 3:** 36 | 37 | ``` 38 | 输入:digits = "2" 39 | 输出:["a","b","c"] 40 | ``` 41 | 42 | ## 回溯 43 | 44 | 经典的全排列,比组合简单多了 45 | 46 | ```go 47 | var phoneMap map[string]string = map[string]string{ 48 | "2": "abc", 49 | "3": "def", 50 | "4": "ghi", 51 | "5": "jkl", 52 | "6": "mno", 53 | "7": "pqrs", 54 | "8": "tuv", 55 | "9": "wxyz", 56 | } 57 | 58 | func letterCombinations(digits string) []string { 59 | if digits == "" { 60 | return []string{} 61 | } 62 | res := make([]string, 0) 63 | var bt func(index int, combination string) 64 | bt = func(index int, combination string) { 65 | if index == len(digits) { 66 | res = append(res, combination) 67 | // tmpStr = "" 68 | return 69 | } 70 | 71 | for _, word := range phoneMap[string(digits[index])] { 72 | bt(index+1, combination+string(word)) 73 | } 74 | } 75 | bt(0, "") 76 | return res 77 | } 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/剑指 Offer 36. 二叉搜索树与双向链表.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 36. 二叉搜索树与双向链表 2 | 3 | `mid` 4 | 5 | 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。 6 | 7 | 以下面的二叉搜索树为例: 8 | 9 | img 10 | 11 | 我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。 12 | 13 | 下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。 14 | 15 | img 16 | 17 | 特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。 18 | 19 | ## DFS 20 | 21 | 二叉树中序遍历模板 22 | 23 | 1. 双指针记录头结点和前驱 24 | 2. 中序遍历顺着 Left 指针入栈,为了不破坏次序。利用 Right 指针在回溯的过程中指向上一层的节点(强行解释)。但已经回溯到上一层时怎么利用之前的节点呢。那就用 pre 变量保存前驱节点。当前节点(实际上已经回溯到上一层了)的 Left 指针指向前驱。这样约定好了之后。递归处理即可 25 | 3. 置为双向循环链表 26 | 27 | ```go 28 | func treeToDoublyList(root *TreeNode) *TreeNode { 29 | if root == nil { 30 | return nil 31 | } 32 | var pre, head *TreeNode 33 | 34 | var inOrder func(root *TreeNode) 35 | inOrder = func(root *TreeNode) { 36 | if root == nil { 37 | return 38 | } 39 | 40 | inOrder(root.Left) 41 | 42 | if pre == nil { 43 | // 遍历到头节点 44 | head = root 45 | } 46 | root.Left = pre 47 | pre.Right = root 48 | 49 | pre = root 50 | 51 | inOrder(root.Right) 52 | } 53 | inOrder(root) 54 | // pre最终指向尾结点 55 | pre.Right = head 56 | head.Left = pre 57 | return head 58 | } 59 | ``` 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/剑指 Offer 54. 二叉搜索树的第k大节点.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 54. 二叉搜索树的第k大节点 2 | 3 | 给定一棵二叉搜索树,请找出其中第 `k` 大的节点的值。 4 | 5 | **示例 1:** 6 | 7 | ``` 8 | 输入: root = [3,1,4,null,2], k = 1 9 | 3 10 | / \ 11 | 1 4 12 | \ 13 | 2 14 | 输出: 4 15 | ``` 16 | 17 | ``` 18 | 输入: root = [5,3,6,2,4,null,null,1], k = 3 19 | 5 20 | / \ 21 | 3 6 22 | / \ 23 | 2 4 24 | / 25 | 1 26 | 输出: 4 27 | ``` 28 | 29 | ## DFS 30 | 31 | 中序遍历倒序,即中右左,这样就能转化为求中序遍历倒序第 k 个结点值 32 | 33 | ```go 34 | func kthLargest(root *TreeNode, k int) int { 35 | var dfs func(root *TreeNode) 36 | var i, res int 37 | dfs = func(root *TreeNode) { 38 | if root == nil { 39 | return 40 | } 41 | dfs(root.Right) 42 | i++ 43 | if i == k { 44 | res = root.Val 45 | } 46 | dfs(root.Left) 47 | } 48 | dfs(root) 49 | return res 50 | } 51 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/back tracking/剑指 Offer 64. 求1+2+…+n.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 64. 求1+2+…+n" 3 | date: 2022-02-27 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,回溯] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 64. 求1+2+…+n 12 | 13 | `mid` 14 | 15 | 求 `1+2+...+n` ,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句(A?B:C)。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入: n = 3 21 | 输出: 6 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入: n = 9 28 | 输出: 45 29 | ``` 30 | 31 | ## 逻辑与算符短路 32 | 33 | ![image-20220227215248107](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220227215248107.png) 34 | 35 | ```go 36 | // 逻辑短路 37 | func sumNums(n int) int { 38 | res := 0 39 | var sum func(n int) bool 40 | sum = func(n int) bool { 41 | res += n 42 | return n > 0 && sum(n-1) // 不满足n>1时 递归就会退出 43 | } 44 | sum(n) 45 | return res 46 | } 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/greedy/55. 跳跃游戏.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "10. 正则表达式匹配" 3 | date: 2022-03-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 贪心, dp] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 55. 跳跃游戏 12 | 13 | 给定一个非负整数数组 nums ,你最初位于数组的 **第一个下标** 。 14 | 15 | 数组中的每个元素代表你在该位置可以跳跃的最大长度。 16 | 17 | 判断你是否能够到达最后一个下标。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:nums = [2,3,1,1,4] 23 | 输出:true 24 | 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:nums = [3,2,1,0,4] 31 | 输出:false 32 | 解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。 33 | ``` 34 | 35 | ## 贪心 36 | 37 | 一次遍历,每次循环内更新能跳到的最远位置 38 | 39 | ```go 40 | func canJump(nums []int) bool { 41 | maxIndex := 0 42 | for i := 0; i < len(nums); i++ { 43 | if i > maxIndex { 44 | return false 45 | } 46 | // 更新能跳到的最远位置 47 | if nums[i]+i > maxIndex { 48 | maxIndex = nums[i] + i 49 | } 50 | } 51 | return true // 能结束遍历说明必能跳到最后 52 | } 53 | ``` 54 | 55 | ## DP 56 | 57 | 比较愚蠢的 dp 58 | 59 | ```go 60 | func canJump(nums []int) bool { 61 | dp := make([]bool, len(nums)) 62 | dp[0] = true 63 | for i := 1; i < len(nums); i++ { 64 | flag := false 65 | for j := i - 1; j >= 0; j-- { 66 | // 遍历之前的每个dp 67 | if dp[j] && nums[j] >= i-j { 68 | flag = true 69 | break 70 | } 71 | } 72 | if flag { 73 | dp[i] = true 74 | } 75 | } 76 | return dp[len(nums)-1] 77 | } 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/141. 环形链表.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "141. 环形链表" 3 | date: 2022-02-23 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [算法] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 141. 环形链表 12 | 13 | 给你一个链表的头节点 `head` ,判断链表中是否有环。 14 | 15 | 如果链表中有某个节点,可以通过连续跟踪 `next` 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 `pos` 来表示链表尾连接到链表中的位置(索引从 0 开始)。**注意:`pos` 不作为参数进行传递** 。仅仅是为了标识链表的实际情况。 16 | 17 | *如果链表中存在环* ,则返回 `true` 。 否则,返回 `false` 。 18 | 19 | image-20220222173816132 20 | 21 | ## 哈希表 22 | 23 | ```go 24 | // 非常朴素的哈希表 25 | func hasCycle(head *ListNode) bool { 26 | hash := make(map[*ListNode]bool) 27 | for head != nil { 28 | if _, ok := hash[head]; ok { 29 | return true 30 | } 31 | hash[head] = true 32 | head = head.Next 33 | } 34 | return false 35 | } 36 | ``` 37 | 38 | ## 快慢指针 39 | 40 | fast 每次走两步,slow 每次走一步,若是循环链表一定会相遇 41 | 42 | ```go 43 | // 非常高级的双指针 44 | func hasCycle2(head *ListNode) bool { 45 | slow, fast := head, head 46 | for slow != nil && fast != nil && fast.Next != nil { 47 | slow = slow.Next 48 | fast = fast.Next.Next 49 | if slow == fast { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/142. 环形链表 II.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "142. 环形链表 II" 3 | date: 2022-03-09 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表, 双指针, 数学] 7 | categories: [算法] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 142. 环形链表 II 12 | 13 | 给定一个链表的头节点 `head` ,返回链表开始入环的第一个节点。 *如果链表无环,则返回 `null`。* 14 | 15 | **示例 1:** 16 | 17 | ![img](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/circularlinkedlist.png) 18 | 19 | ``` 20 | 输入:head = [3,2,0,-4], pos = 1 21 | 输出:返回索引为 1 的链表节点 22 | 解释:链表中有一个环,其尾部连接到第二个节点 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ![img](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/circularlinkedlist_test2.png) 28 | 29 | ``` 30 | 输入:head = [1,2], pos = 0 31 | 输出:返回索引为 0 的链表节点 32 | 解释:链表中有一个环,其尾部连接到第一个节点。 33 | ``` 34 | 35 | # 快慢指针 + 数学 36 | 37 | slow 走一步,fast 走两步,一定会相遇 38 | 39 | 相遇后,建个 p 从头走,slow 继续走,相遇点即为第一个公共结点 40 | 41 | 证明详见:https://www.programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#_142-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8ii 42 | 43 | ```go 44 | func detectCycle(head *ListNode) *ListNode { 45 | slow, fast := head, head 46 | for fast != nil && fast.Next != nil { 47 | slow = slow.Next 48 | fast = fast.Next.Next 49 | if slow == fast { 50 | for slow != head { 51 | slow = slow.Next 52 | head = head.Next 53 | } 54 | return head 55 | } 56 | } 57 | return nil 58 | } 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/19. 删除链表的倒数第 N 个结点.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "19. 删除链表的倒数第 N 个结点" 3 | date: 2022-03-08 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [算法] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 19. 删除链表的倒数第 N 个结点 12 | 13 | ## 快慢指针 14 | 15 | 伪头节点真香,删除头节点很方便 16 | 17 | ```go 18 | func removeNthFromEnd(head *ListNode, n int) *ListNode { 19 | if head.Next == nil { 20 | return nil 21 | } 22 | fakeHead := &ListNode{Next: head} 23 | pre, p, q := fakeHead, head, head 24 | for i := 0; i < n; i++ { 25 | q = q.Next 26 | } 27 | for q != nil { 28 | pre = p 29 | p = p.Next 30 | q = q.Next 31 | } 32 | pre.Next = p.Next 33 | return fakeHead.Next 34 | } 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/206. 反转链表.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "206. 反转链表" 3 | date: 2022-03-08 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [算法] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 206. 反转链表 12 | 13 | 给你单链表的头节点 `head` ,请你反转链表,并返回反转后的链表。 14 | 15 | **示例 1:** 16 | 17 | ![img](https://assets.leetcode.com/uploads/2021/02/19/rev1ex1.jpg) 18 | 19 | ``` 20 | 输入:head = [1,2,3,4,5] 21 | 输出:[5,4,3,2,1] 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ![img](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/rev1ex2.jpg) 27 | 28 | ``` 29 | 输入:head = [1,2] 30 | 输出:[2,1] 31 | ``` 32 | 33 | **示例 3:** 34 | 35 | ``` 36 | 输入:head = [] 37 | 输出:[] 38 | ``` 39 | 40 | ## :star: 双指针 41 | 42 | ```go 43 | func reverseList(head *ListNode) *ListNode { 44 | if head == nil { 45 | return nil 46 | } 47 | var pre, cur *ListNode = nil, head 48 | for cur != nil { 49 | tmp := cur.Next 50 | cur.Next = pre 51 | pre = cur 52 | cur = tmp 53 | } 54 | return pre 55 | } 56 | ``` 57 | 58 | ## 递归 59 | 60 | 实质上和双指针一样 61 | 62 | ```go 63 | func reverseList(head *ListNode) *ListNode { 64 | var reverse func(pre, cur *ListNode) *ListNode 65 | reverse = func(pre, cur *ListNode) *ListNode { 66 | if cur == nil { 67 | return pre 68 | } 69 | after := cur.Next 70 | cur.Next = pre 71 | return reverse(cur, after) 72 | } 73 | return reverse(nil, head) 74 | } 75 | ``` 76 | 77 | ## 另一种递归 78 | 79 | 很妙啊 80 | 81 | ```go 82 | func reverseList(head *ListNode) *ListNode { 83 | if head == nil { 84 | return nil 85 | } 86 | if head.Next == nil { 87 | return head 88 | } 89 | last := reverseList(head.Next) 90 | head.Next.Next = head // 翻转头节点与第二个节点的指向 91 | head.Next = nil 92 | return last 93 | } 94 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/234. 回文链表.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "234. 回文链表" 3 | date: 2022-08-08 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 234. 回文链表 12 | 13 | `easy` 14 | 15 | 给你一个单链表的头节点 `head` ,请你判断该链表是否为回文链表。如果是,返回 `true` ;否则,返回 `false` 16 | 17 | image-20220808114349967 18 | 19 | ## 快慢指针 + 反转 20 | 21 | 利用快慢指针将链表分割成前后两部分,然后反转后半部分链表,就可以一一比较了 22 | 23 | ```go 24 | package linked_list 25 | 26 | func isPalindrome(head *ListNode) bool { 27 | if head == nil { 28 | return true 29 | } 30 | slow, fast := head, head 31 | for fast.Next != nil && fast.Next.Next != nil { 32 | slow = slow.Next 33 | fast = fast.Next.Next 34 | } 35 | // slow 即为前半部分的尾节点,如果链表为奇数,那么slow为中间节点 36 | 37 | startOfSecondHalf := reverseList(slow.Next) // 后半部分的头节点 顺便反转一下后半部分 38 | 39 | p, q := head, startOfSecondHalf 40 | for q != nil { 41 | if p.Val != q.Val { 42 | return false 43 | } 44 | p, q = p.Next, q.Next 45 | } 46 | return true 47 | 48 | } 49 | 50 | func reverseList(head *ListNode) *ListNode { 51 | if head == nil { 52 | return nil 53 | } 54 | var pre, cur *ListNode = nil, head 55 | for cur != nil { 56 | tmp := cur.Next 57 | cur.Next = pre 58 | pre, cur = cur, tmp 59 | } 60 | return pre 61 | } 62 | ``` 63 | 64 | 时间复杂度:O(n),其中 n 指的是链表的大小。 65 | 66 | 空间复杂度:O(1),我们只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1) -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/24. 两两交换链表中的节点.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "24. 两两交换链表中的节点" 3 | date: 2022-08-03 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,链表] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 24. 两两交换链表中的节点 12 | 13 | `mid` 14 | 15 | 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 16 | 17 | image-20220803124235069 18 | 19 | ## 迭代 20 | 21 | 简单 22 | 23 | 用个伪头节点记录初始位置 24 | 25 | ```go 26 | func swapPairs(head *ListNode) *ListNode { 27 | fakeHead := &ListNode{Next: head} 28 | pre := fakeHead 29 | for pre.Next != nil && pre.Next.Next != nil { 30 | p, q := pre.Next, pre.Next.Next 31 | // p q 交换 32 | pre.Next = q 33 | p.Next = q.Next 34 | q.Next = p 35 | 36 | pre = p 37 | } 38 | return fakeHead.Next 39 | } 40 | ``` 41 | 42 | ## 递归 43 | 44 | 先交换头两个节点,之后的节点递归交换,其实还是迭代的思想 45 | 46 | ```go 47 | func swapPairs(head *ListNode) *ListNode { 48 | if head == nil || head.Next == nil { 49 | return head 50 | } 51 | 52 | p, q := head, head.Next 53 | p.Next = q.Next 54 | q.Next = p 55 | p.Next = swapPairs(p.Next) 56 | 57 | return q 58 | } 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/287. 寻找重复数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "287. 寻找重复数" 3 | date: 2022-08-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 287. 寻找重复数 12 | 13 | `mid` 14 | 15 | 给定一个包含 `n + 1` 个整数的数组 `nums` ,其数字都在 `[1, n]` 范围内(包括 `1` 和 `n`),可知至少存在一个重复的整数。 16 | 17 | 假设 `nums` 只有 **一个重复的整数** ,返回 **这个重复的数** 。 18 | 19 | 你设计的解决方案必须 **不修改** 数组 `nums` 且只用常量级 `O(1)` 的额外空间。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:nums = [1,3,4,2,2] 25 | 输出:2 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:nums = [3,1,3,4,2] 32 | 输出:3 33 | ``` 34 | 35 | ## 抽象成循环链表问题 36 | 37 | 本题可以使用数组配合下标,抽象成链表问题,用快慢指针可解 38 | 39 | ![image-20220810152203331](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220810152203331.png) 40 | 41 | ```go 42 | func findDuplicate(nums []int) int { 43 | slow, fast := 0, 0 44 | for fast != slow || fast == 0 { 45 | // slow走一步 fast走两步 直到相遇 46 | slow = nums[slow] 47 | fast = nums[nums[fast]] 48 | } 49 | 50 | start := 0 // 设start从头走 51 | for start != slow { 52 | start = nums[start] 53 | slow = nums[slow] 54 | } 55 | return slow 56 | } 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/剑指 Offer 06. 从尾到头打印链表.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 06. 从尾到头打印链表 2 | 3 | `easy` 4 | 5 | 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 6 | 7 | **示例 1:** 8 | 9 | ``` 10 | 输入:head = [1,3,2] 11 | 输出:[2,3,1] 12 | ``` 13 | 14 | ## 辅助栈 15 | 16 | ```go 17 | // 辅助栈 18 | func reversePrint(head *ListNode) []int { 19 | var stack []int 20 | for p := head; p != nil; p = p.Next { 21 | stack = append(stack, p.Val) 22 | } 23 | var result []int 24 | for i := len(stack) - 1; i >= 0; i-- { 25 | result = append(result, stack[i]) 26 | } 27 | return result 28 | } 29 | ``` 30 | 31 | ## 递归 32 | 33 | ```go 34 | // 递归 35 | func reversePrint(head *ListNode) []int { 36 | if head == nil { 37 | return []int{} 38 | } 39 | return append(reversePrint(head.Next), head.Val) 40 | } 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/剑指 Offer 18. 删除链表的节点.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 18. 删除链表的节点 2 | 3 | `easy` 4 | 5 | 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。 6 | 7 | 返回删除后的链表的头节点。 8 | 9 | 注意:此题对比原题有改动 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入: head = [4,5,1,9], val = 5 15 | 输出: [4,1,9] 16 | 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入: head = [4,5,1,9], val = 1 23 | 输出: [4,5,9] 24 | 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. 25 | ``` 26 | 27 | > 题目保证链表中节点的值互不相同 28 | 29 | ## 双指针 30 | 31 | preNode 和 curNode 32 | 33 | ```go 34 | func deleteNode(head *ListNode, val int) *ListNode { 35 | if head.Val == val { 36 | return head.Next 37 | } 38 | preNode := head 39 | curNode := head 40 | for curNode != nil { 41 | if curNode.Val == val { 42 | preNode.Next = curNode.Next 43 | return head 44 | } 45 | preNode = curNode 46 | curNode = curNode.Next 47 | } 48 | return head 49 | } 50 | ``` 51 | 52 | ## 递归 53 | 54 | ```go 55 | func deleteNode(head *ListNode, val int) *ListNode { 56 | if head == nil { 57 | return nil 58 | } 59 | if head.Val == val { 60 | return head.Next 61 | } 62 | 63 | head.Next = deleteNode(head.Next, val) 64 | return head 65 | } 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/剑指 Offer 22. 链表中倒数第 k 个节点.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 22. 链表中倒数第 k 个节点" 3 | date: 2022-02-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [算法] 8 | --- 9 | 10 | # 剑指 Offer 22. 链表中倒数第 k 个节点 11 | 12 | `easy` 13 | 14 | 输入一个链表,**输出该链表中倒数第 k 个节点**。为了符合大多数人的习惯,本题从 1 开始计数,即链表的尾节点是倒数第 1 个节点。 15 | 16 | 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。 17 | 18 | **示例:** 19 | 20 | ``` 21 | 给定一个链表: 1->2->3->4->5, 和 k = 2. 22 | 23 | 返回链表 4->5. 24 | ``` 25 | 26 | ## 双指针 27 | 28 | fast 先走 k 步,然后 slow 和 fast 一起走,直到 fast 走到空 29 | 30 | ```go 31 | func getKthFromEnd(head *ListNode, k int) *ListNode { 32 | curNode, preNode := head, head 33 | for curNode != nil { 34 | curNode = curNode.Next 35 | if k == 0 { 36 | preNode = preNode.Next 37 | } else { 38 | k-- 39 | } 40 | } 41 | return preNode 42 | } 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/剑指 Offer 24. 反转链表.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 24. 反转链表" 3 | date: 2022-02-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [算法] 8 | --- 9 | 10 | # 剑指 Offer 24. 反转链表 11 | 12 | `easy` 13 | 14 | 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。 15 | 16 | **示例:** 17 | 18 | ``` 19 | 输入: 1->2->3->4->5->NULL 20 | 输出: 5->4->3->2->1->NULL 21 | ``` 22 | 23 | ## 三指针 24 | 25 | ```go 26 | // 三指针 27 | func reverseList(head *ListNode) *ListNode { 28 | var prev, next *ListNode // 默认为nil 29 | cur := head 30 | for cur != nil { 31 | next = cur.Next 32 | cur.Next = prev 33 | prev = cur 34 | cur = next 35 | } 36 | return prev 37 | } 38 | ``` 39 | 40 | ## 递归 41 | 42 | ```go 43 | // 递归 44 | func reverseList2(head *ListNode) *ListNode { 45 | if head == nil || head.Next == nil { 46 | return head 47 | } 48 | newHead := reverseList2(head.Next) 49 | head.Next.Next = head 50 | head.Next = nil 51 | return newHead 52 | } 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/link list/剑指 Offer 25. 合并两个排序的链表.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 25. 合并两个排序的链表" 3 | date: 2022-02-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 链表] 7 | categories: [算法] 8 | --- 9 | 10 | # 剑指 Offer 25. 合并两个排序的链表 11 | 12 | `easy` 13 | 14 | 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。 15 | 16 | **示例1:** 17 | 18 | ``` 19 | 输入:1->2->4, 1->3->4 20 | 输出:1->1->2->3->4->4 21 | ``` 22 | 23 | ## 归并排序 24 | 25 | 本质上也是个双指针 26 | 27 | ```go 28 | func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { 29 | fakeHead := &ListNode{} // 伪头节点 30 | curNode := fakeHead 31 | for l1 != nil || l2 != nil { 32 | if l1 == nil { 33 | curNode.Next = l2 34 | break 35 | } 36 | if l2 == nil { 37 | curNode.Next = l1 38 | break 39 | } 40 | 41 | if l1.Val > l2.Val { 42 | curNode.Next = l2 43 | l2 = l2.Next 44 | } else { 45 | curNode.Next = l1 46 | l1 = l1.Next 47 | } 48 | curNode = curNode.Next 49 | } 50 | return fakeHead.Next 51 | } 52 | ``` 53 | 54 | 伪头节点真的能减少很多边界条件的考虑! 55 | 56 | 不用伪头节点的情况,很繁琐: 57 | 58 | ```go 59 | func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { 60 | if l1 == nil { 61 | return l2 62 | } else if l2 == nil { 63 | return l1 64 | } 65 | 66 | var head *ListNode 67 | if l1.Val > l2.Val { 68 | head = l2 69 | l2 = l2.Next 70 | } else { 71 | head = l1 72 | l1 = l1.Next 73 | } 74 | curNode := head 75 | for l1 != nil || l2 != nil { 76 | if l1 == nil { 77 | curNode.Next = l2 78 | break 79 | } 80 | if l2 == nil { 81 | curNode.Next = l1 82 | break 83 | } 84 | 85 | if l1.Val > l2.Val { 86 | curNode.Next = l2 87 | l2 = l2.Next 88 | } else { 89 | curNode.Next = l1 90 | l1 = l1.Next 91 | } 92 | curNode = curNode.Next 93 | } 94 | return head 95 | } 96 | ``` 97 | 98 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/1374. 生成每种字符都是奇数个的字符串.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1374. 生成每种字符都是奇数个的字符串" 3 | date: 2022-8-1 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 哈希, 双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 1374. 生成每种字符都是奇数个的字符串 12 | 13 | `easy` 14 | 15 | 给你一个整数 `n`,请你返回一个含 *`n`* 个字符的字符串,其中每种字符在该字符串中都恰好出现 **奇数次** ***。*** 16 | 17 | 返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串,则返回其中任意一个即可。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:n = 4 23 | 输出:"pppz" 24 | 解释:"pppz" 是一个满足题目要求的字符串,因为 'p' 出现 3 次,且 'z' 出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:"ohhh" 和 "love"。 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:n = 2 31 | 输出:"xy" 32 | 解释:"xy" 是一个满足题目要求的字符串,因为 'x' 和 'y' 各出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:"ag" 和 "ur"。 33 | ``` 34 | 35 | ## 判断奇偶 36 | 37 | 什么傻逼题 38 | 39 | ```go 40 | import "strings" 41 | 42 | func generateTheString(n int) string { 43 | if n%2 == 0 { 44 | return strings.Repeat("a", n-1) + "b" 45 | } else { 46 | return strings.Repeat("a", n) 47 | } 48 | } 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/202. 快乐数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "202. 快乐数" 3 | date: 2022-03-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 哈希, 双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 202. 快乐数 12 | 13 | `easy` 14 | 15 | 编写一个算法来判断一个数 `n` 是不是快乐数。 16 | 17 | **「快乐数」** 定义为: 18 | 19 | - 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 20 | - 然后重复这个过程直到这个数变为 1,也可能是 **无限循环** 但始终变不到 1。 21 | 22 | - 如果这个过程 **结果为** 1,那么这个数就是快乐数。 23 | 24 | **示例 1:** 25 | 26 | ``` 27 | 输入:n = 19 28 | 输出:true 29 | 解释: 30 | 1^2 + 9^2 = 82 31 | 8^2 + 2^2 = 68 32 | 6^2 + 8^2 = 100 33 | 1^2 + 0^2 + 0^2 = 1 34 | ``` 35 | 36 | **示例 2:** 37 | 38 | ``` 39 | 输入:n = 2 40 | 输出:false 41 | ``` 42 | 43 | ## 哈希表 44 | 45 | 没别哒,就是把每一次的计算结果存起来,因为不是从头循环 46 | 47 | ```go 48 | func isHappy(n int) bool { 49 | hash := make(map[int]bool) 50 | sum := n 51 | for !hash[sum] { 52 | hash[sum] = true 53 | sum = getSum(sum) 54 | if sum == 1 { 55 | return true 56 | } 57 | } 58 | return false 59 | } 60 | 61 | func getSum(n int) int { 62 | sum := 0 63 | for n > 0 { 64 | sum += (n % 10) * (n % 10) 65 | n /= 10 66 | } 67 | return sum 68 | } 69 | ``` 70 | 71 | ## 快慢指针 72 | 73 | 慢指针走一步,快指针走两步,一定会相遇(都为 1 也是相遇的) 74 | 75 | ```go 76 | func getSum(n int) int { 77 | sum := 0 78 | for n > 0 { 79 | sum += (n % 10) * (n % 10) 80 | n /= 10 81 | } 82 | return sum 83 | } 84 | 85 | // 非常妙的快慢指针 86 | func isHappy(n int) bool { 87 | slowSum, fastSum := n, n 88 | for { 89 | slowSum = getSum(slowSum) 90 | fastSum = getSum(fastSum) 91 | fastSum = getSum(fastSum) 92 | if slowSum == fastSum { 93 | break 94 | } 95 | } 96 | return slowSum == 1 97 | } 98 | ``` 99 | 100 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/7. 整数反转.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "7. 整数反转" 3 | date: 2022-02-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数学] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 7. 整数反转 12 | 13 | `mid` 14 | 15 | 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 16 | 17 | 如果反转后整数超过 32 位的有符号整数的范围 [−2^31^, 2^31^ − 1] ,就返回 0。 18 | 19 | 假设环境不允许存储 64 位整数(有符号或无符号)。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:x = 123 25 | 输出:321 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:x = -123 32 | 输出:-321 33 | ``` 34 | 35 | **示例 3:** 36 | 37 | ``` 38 | 输入:x = 120 39 | 输出:21 40 | ``` 41 | 42 | ## 数学 43 | 44 | ```go 45 | import math 46 | 47 | func reverse(x int) int { 48 | var digit, res int 49 | for x != 0 { 50 | if res < math.MinInt32/10 || res > math.MaxInt32/10 { 51 | return 0 52 | } 53 | digit = x % 10 // 个位 54 | x /= 10 55 | res = res*10 + digit 56 | } 57 | return res 58 | } 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/9. 回文数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "9. 回文数" 3 | date: 2022-03-07 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数学] 7 | categories: [刷题] 8 | --- 9 | 10 | # 9. 回文数 11 | 12 | 给你一个整数 `x` ,如果 `x` 是一个回文整数,返回 `true` ;否则,返回 `false` 。 13 | 14 | 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 15 | 16 | - 例如,`121` 是回文,而 `123` 不是。 17 | 18 | **示例 1:** 19 | 20 | ``` 21 | 输入:x = 121 22 | 输出:true 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:x = -121 29 | 输出:false 30 | 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 31 | ``` 32 | 33 | ## 转字符串 34 | 35 | 比较无脑 36 | 37 | ```go 38 | func isPalindrome(x int) bool { 39 | if x < 0 { 40 | return false 41 | } 42 | arr := make([]int, 0) 43 | for x > 0 { 44 | arr = append(arr, x%10) 45 | x /= 10 46 | } 47 | l, r := 0, len(arr)-1 48 | for l <= r { 49 | if arr[l] != arr[r] { 50 | return false 51 | } 52 | l++ 53 | r-- 54 | } 55 | return true 56 | } 57 | ``` 58 | 59 | ## 反转一半数字 60 | 61 | image-20220307230339047 62 | 63 | ```go 64 | func isPalindrome(x int) bool { 65 | // 特殊情况: 66 | // 如上所述,当 x < 0 时,x 不是回文数。 67 | // 同样地,如果数字的最后一位是 0,为了使该数字为回文, 68 | // 则其第一位数字也应该是 0 69 | // 只有 0 满足这一属性 70 | if x < 0 || (x%10 == 0 && x != 0) { 71 | return false 72 | } 73 | 74 | revertedNumber := 0 75 | for x > revertedNumber { 76 | revertedNumber = revertedNumber*10 + x%10 77 | x /= 10 78 | } 79 | 80 | // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。 81 | // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123, 82 | // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。 83 | return x == revertedNumber || x == revertedNumber/10 84 | } 85 | 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/剑指 Offer 15. 二进制中 1 的个数.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 15. 二进制中 1 的个数" 3 | date: 2022-03-03 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,位运算] 7 | categories: [刷题] 8 | --- 9 | 10 | # 剑指 Offer 15. 二进制中 1 的个数 11 | 12 | `easy` 13 | 14 | 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 [汉明重量](http://en.wikipedia.org/wiki/Hamming_weight)).)。 15 | 16 | **示例 1:** 17 | 18 | ``` 19 | 输入:n = 11 (控制台输入 00000000000000000000000000001011) 20 | 输出:3 21 | 解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1' 22 | ``` 23 | 24 | ## 位运算 25 | 26 | ```go 27 | func hammingWeight(num uint32) (count int) { 28 | for num > 0 { 29 | if num&1 == 1 { 30 | count++ 31 | } 32 | num = num >> 1 33 | } 34 | return 35 | } 36 | ``` 37 | 38 | ![image-20220303200414645](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220303200414645.png) 39 | 40 | ```go 41 | func hammingWeight(num uint32) (ones int) { 42 | for i := 0; i < 32; i++ { 43 | if 1< 0 { 44 | ones++ 45 | } 46 | } 47 | return 48 | } 49 | ``` 50 | 51 | ![image-20220303200438396](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220303200438396.png) 52 | 53 | ## 位运算优化 54 | 55 | ![image-20220303200456215](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220303200456215.png) 56 | 57 | ```go 58 | func hammingWeight(num uint32) (ones int) { 59 | for ; num > 0; num &= num - 1 { 60 | ones++ 61 | } 62 | return 63 | } 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/剑指 Offer 16. 数值的整数次方.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 16. 数值的整数次方" 3 | date: 2022-03-03 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,数学] 7 | categories: [刷题] 8 | --- 9 | 10 | # 剑指 Offer 16. 数值的整数次方 11 | 12 | `easy` 13 | 14 | 实现 [pow(*x*, *n*)](https://www.cplusplus.com/reference/valarray/pow/) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。 15 | 16 | **示例 1:** 17 | 18 | ``` 19 | 输入:x = 2.00000, n = 10 20 | 输出:1024.00000 21 | ``` 22 | 23 | ## 快速幂(二进制) 24 | 25 | image-20220303142146455 26 | 27 | image-20220303142152801 28 | 29 | image-20220303142245915 30 | 31 | ![image-20220303161004959](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220303161004959.png) 32 | 33 | ```go 34 | func myPow(x float64, n int) float64 { 35 | if x == 0 { 36 | return 0 37 | } 38 | if n < 0 { 39 | x, n = 1/x, -n 40 | } 41 | res := 1.0 42 | var b int // 二进制n的某一位 0或1 43 | for n != 0 { 44 | b = n & 1 // 获取二进制n最后一位 45 | if b != 0 { 46 | res *= x 47 | } 48 | n = n >> 1 // n右移一位 49 | x = x * x 50 | } 51 | return res 52 | } 53 | ``` 54 | 55 | ## 二分法角度理解 56 | 57 | image-20220303142442030 -------------------------------------------------------------------------------- /content/posts/专业/刷题/others/剑指 Offer 65. 不用加减乘除做加法.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 65. 不用加减乘除做加法" 3 | date: 2022-03-03 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,位运算] 7 | categories: [刷题] 8 | --- 9 | 10 | # 剑指 Offer 65. 不用加减乘除做加法 11 | 12 | `easy` 13 | 14 | 写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。 15 | 16 | **示例:** 17 | 18 | ``` 19 | 输入: a = 1, b = 1 20 | 输出: 2 21 | ``` 22 | 23 | **提示:** 24 | 25 | - `a`, `b` 均可能是负数或 0 26 | - 结果不会溢出 32 位整数 27 | 28 | ## 位运算 29 | 30 | ![image-20220303204314920](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220303204314920.png) 31 | 32 | ```go 33 | func add(a int, b int) int { 34 | // 进位 35 | var carry int 36 | for b != 0 { 37 | // 进位 38 | carry = (a & b) << 1 39 | // 不加进位 40 | a ^= b 41 | // 加进位 42 | b = carry 43 | } 44 | 45 | return a 46 | } 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/1047. 删除字符串中的所有相邻重复项.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1047. 删除字符串中的所有相邻重复项" 3 | date: 2022-04-06 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 栈] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 1047. 删除字符串中的所有相邻重复项 12 | 13 | `easy` 14 | 15 | 给出由小写字母组成的字符串 `S`,**重复项删除操作**会选择两个相邻且相同的字母,并删除它们。 16 | 17 | 在 S 上反复执行重复项删除操作,直到无法继续删除。 18 | 19 | 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 20 | 21 | **示例:** 22 | 23 | ``` 24 | 输入:"abbaca" 25 | 输出:"ca" 26 | 解释:例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。 27 | ``` 28 | 29 | ## 栈! 30 | 31 | 每次入栈时,判断待入栈字母与栈顶字母是否相同,是的话就一并消除 32 | 33 | ```go 34 | func removeDuplicates(s string) string { 35 | if len(s) == 0 { 36 | return "" 37 | } 38 | stack := make([]byte, 0) 39 | for i := 0; i < len(s); i++ { 40 | if len(stack) != 0 && s[i] == stack[len(stack)-1] { 41 | // 待入栈的字母与栈顶字母相同 42 | stack = stack[:len(stack)-1] 43 | } else { 44 | stack = append(stack, s[i]) 45 | } 46 | } 47 | return string(stack) 48 | } 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/12. 整数转罗马数字.md: -------------------------------------------------------------------------------- 1 | # 整数转罗马数字 2 | 3 | `mid` 4 | 5 | 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 6 | 7 | ```text 8 | 字符 数值 9 | I 1 10 | V 5 11 | X 10 12 | L 50 13 | C 100 14 | D 500 15 | M 1000 16 | ``` 17 | 18 | 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 19 | 20 | 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: 21 | 22 | - I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 23 | - X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 24 | - C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 25 | 26 | 给你一个整数,将其转为罗马数字。 27 | 28 | ```text 29 | 示例 1: 30 | 31 | 输入: num = 3 32 | 输出: "III" 33 | 34 | 示例 2: 35 | 36 | 输入: num = 4 37 | 输出: "IV" 38 | 39 | 示例 3: 40 | 41 | 输入: num = 9 42 | 输出: "IX" 43 | 44 | 示例 4: 45 | 46 | 输入: num = 58 47 | 输出: "LVIII" 48 | 解释: L = 50, V = 5, III = 3. 49 | 50 | 示例 5: 51 | 52 | 输入: num = 1994 53 | 输出: "MCMXCIV" 54 | 解释: M = 1000, CM = 900, XC = 90, IV = 4. 55 | ``` 56 | 57 | ## 解 58 | 59 | 依照题意,优先选择大的数字,解题思路采用贪心算法。将 1-3999 范围内的罗马数字从大到小放在数组中,从头选择到尾,即可把整数转成罗马数字。 60 | 61 | ```go 62 | func intToRoman(num int) string { 63 | values := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1} 64 | symbols := []string{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"} 65 | res, i := "", 0 66 | for num != 0 { 67 | for values[i] > num { 68 | i++ 69 | } 70 | num -= values[i] 71 | res += symbols[i] 72 | } 73 | return res 74 | } 75 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/13. 罗马数字转整数.md: -------------------------------------------------------------------------------- 1 | # 13. 罗马数字转整数 2 | 3 | `easy` 4 | 5 | 给定一个罗马数字,将其转换成整数。 6 | 7 | **示例 1:** 8 | 9 | ``` 10 | 输入: s = "III" 11 | 输出: 3 12 | ``` 13 | 14 | **示例 2:** 15 | 16 | ``` 17 | 输入: s = "IV" 18 | 输出: 4 19 | ``` 20 | 21 | ## 解 22 | 23 | 建立一个 HashMap 来映射符号和值,然后对字符串从左到右来,如果当前字符代表的值不小于其右边,就加上该值;否则就减去该值。以此类推 24 | 25 | ```go 26 | func romanToInt(s string) int { 27 | roman := map[string]int{ 28 | "I": 1, 29 | "V": 5, 30 | "X": 10, 31 | "L": 50, 32 | "C": 100, 33 | "D": 500, 34 | "M": 1000, 35 | } 36 | result := 0 37 | for i := 0; i < len(s); i++ { 38 | if i+1 < len(s) && roman[string(s[i])] < roman[string(s[i+1])] { 39 | result -= roman[string(s[i])] 40 | } else { 41 | result += roman[string(s[i])] 42 | } 43 | } 44 | return result 45 | } 46 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/14. 最长公共前缀.md: -------------------------------------------------------------------------------- 1 | # 14. 最长公共前缀 2 | 3 | 编写一个函数来查找字符串数组中的最长公共前缀。 4 | 5 | 如果不存在公共前缀,返回空字符串 `""`。 6 | 7 | **示例 1:** 8 | 9 | ``` 10 | 输入:strs = ["flower","flow","flight"] 11 | 输出:"fl" 12 | ``` 13 | 14 | **示例 2:** 15 | 16 | ``` 17 | 输入:strs = ["dog","racecar","car"] 18 | 输出:"" 19 | 解释:输入不存在公共前缀。 20 | ``` 21 | 22 | ## 解 23 | 24 | ```go 25 | func longestCommonPrefix(strs []string) string { 26 | prefix := strs[0] // 先随便找一个作为前缀 在遍历过程中再慢慢剔除 27 | 28 | for i := 1; i < len(strs); i++ { 29 | // 遍历每个字符串 30 | for j := 0; j < len(prefix); j++ { 31 | // 遍历每个前缀字母 32 | if len(strs[i]) <= j || strs[i][j] != prefix[j] { 33 | prefix = prefix[:j] 34 | break 35 | } 36 | } 37 | } 38 | return prefix 39 | } 40 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/151. 翻转字符串里的单词.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "151. 翻转字符串里的单词" 3 | date: 2022-03-11 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 双指针] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 151. 翻转字符串里的单词 12 | 13 | `mid` 14 | 15 | 给你一个字符串 `s` ,逐个翻转字符串中的所有 **单词** 。 16 | 17 | **单词** 是由非空格字符组成的字符串。`s` 中使用至少一个空格将字符串中的 **单词** 分隔开。 18 | 19 | 请你返回一个翻转 `s` 中单词顺序并用单个空格相连的字符串。 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:s = "the sky is blue" 25 | 输出:"blue is sky the" 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:s = " hello world " 32 | 输出:"world hello" 33 | 解释:颠倒后的字符串中不能存在前导空格和尾随空格。 34 | ``` 35 | 36 | ## 双指针 37 | 38 | 目标是:原地反转,空间复杂度 $O(1)$ 39 | 40 | 1. 去空格:快慢指针 41 | 2. 整体反转:头尾指针 42 | 3. 部分反转:头尾指针 43 | 44 | 要注意去空格的边界条件,因为每一次循环,`slow` 最后要 +1 留一个空格,所以字符串末尾有空格和没空格是有区别的。 45 | 46 | ```go 47 | func reverse(b []byte) { 48 | l, r := 0, len(b)-1 49 | for l <= r { 50 | b[l], b[r] = b[r], b[l] 51 | l++ 52 | r-- 53 | } 54 | } 55 | 56 | func reverseWords(s string) string { 57 | b := []byte(s) 58 | // 移除多余空格 59 | slow, fast := 0, 0 60 | 61 | for fast < len(b) { 62 | // 寻找一个单词的开头 63 | for fast < len(b) && b[fast] == ' ' { 64 | fast++ 65 | } 66 | for fast < len(b) && b[fast] != ' ' { 67 | b[slow], b[fast] = b[fast], b[slow] 68 | slow++ 69 | fast++ 70 | } 71 | slow++ 72 | } 73 | if b[slow-2] == ' ' { 74 | // 字符末尾有空格 75 | b = b[:slow-2] 76 | } else { 77 | // 字符末尾无空格 78 | b = b[:slow-1] 79 | } 80 | 81 | reverse(b) 82 | slow, fast = 0, 0 83 | for fast < len(b) { 84 | for slow < len(b) && b[slow] == ' ' { 85 | slow++ 86 | } 87 | fast = slow 88 | for fast < len(b) && b[fast] != ' ' { 89 | fast++ 90 | } 91 | reverse(b[slow:fast]) 92 | 93 | slow = fast 94 | } 95 | return string(b) 96 | } 97 | ``` 98 | 99 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/242. 有效的字母异位词.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "242. 有效的字母异位词" 3 | date: 2022-03-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 哈希] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 242. 有效的字母异位词 12 | 13 | 给定两个字符串 `s` 和 `t` ,编写一个函数来判断 `t` 是否是 `s` 的字母异位词。 14 | 15 | **注意:**若 `s` 和 `*t*` 中每个字符出现的次数都相同,则称 `s` 和 `t` 互为字母异位词。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入: s = "anagram", t = "nagaram" 21 | 输出: true 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入: s = "rat", t = "car" 28 | 输出: false 29 | ``` 30 | 31 | ## 哈希表 32 | 33 | 用一个 `[26]int` 来代替 `map[byte]int` 34 | 35 | 三个循环 36 | 37 | ```go 38 | func isAnagram(s string, t string) bool { 39 | if len(s) != len(t) { 40 | return false 41 | } 42 | var hash [26]int 43 | for _, letter := range s { 44 | hash[letter-'a']++ 45 | } 46 | for _, letter := range t { 47 | if hash[letter-'a'] == 0 { 48 | return false 49 | } 50 | hash[letter-'a']-- 51 | } 52 | for i := 0; i < 26; i++ { 53 | if hash[i] > 0 { 54 | return false 55 | } 56 | } 57 | return true 58 | // 甚至可以酱紫写 xia 59 | // return record == [26]int{} 60 | } 61 | ``` 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/28. 实现 strStr().md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "28. 实现 strStr()" 3 | date: 2022-03-14 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, KMP] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 28. 实现 `strStr()` 12 | 13 | 实现 [strStr()](https://baike.baidu.com/item/strstr/811469) 函数。 14 | 15 | 给你两个字符串 `haystack` 和 `needle` ,请你在 `haystack` 字符串中找出 `needle` 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 `-1` 。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:haystack = "hello", needle = "ll" 21 | 输出:2 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入:haystack = "aaaaa", needle = "bba" 28 | 输出:-1 29 | ``` 30 | 31 | ## KMP 32 | 33 | ```go 34 | // strStr KMP算法 时间复杂度O(N+M),空间复杂度O(M) 35 | func strStrSimple(haystack string, needle string) int { 36 | n, m := len(haystack), len(needle) 37 | if m == 0 { 38 | return 0 39 | } 40 | next := make([]int, m) 41 | GetNext(next, needle) 42 | // 因为next数组里记录的起始位置为0 43 | j := 0 44 | // i从0开始匹配 45 | for i := 0; i < n; i++ { 46 | // 如果不匹配,就寻找之前匹配的位置 47 | for j > 0 && haystack[i] != needle[j] { 48 | j = next[j-1] 49 | } 50 | // 如果匹配,i和j同时向后移动 51 | if haystack[i] == needle[j] { 52 | j++ 53 | } 54 | // 如果j从0移动到m的位置,意味着模式串needle与文本串haystack匹配成功 55 | if j == m { 56 | return i - m + 1 57 | } 58 | } 59 | return -1 60 | } 61 | 62 | func GetNext(next []int, s string) { 63 | // next[j]就是记录着j(包括j)之前的子串的相同前后缀的长度。 64 | j := 0 65 | next[0] = 0 66 | // j指向前缀起始位置,i指向后缀起始位置 67 | for i := 1; i < len(s); i++ { 68 | // 如果前后缀不相同,那么j就要向前回退 69 | for j > 0 && s[i] != s[j] { 70 | j = next[j-1] 71 | } 72 | // 说明找到了相同的前后缀, j++,同时记录next[i] 73 | if s[i] == s[j] { 74 | j++ 75 | } 76 | next[i] = j 77 | } 78 | } 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/3. 无重复字符的最长子串.md: -------------------------------------------------------------------------------- 1 | # 无重复字符的最长子串 2 | 3 | `mid` 4 | 5 | https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 6 | 7 | 给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。 8 | 9 | 示例 1: 10 | 11 | ``` 12 | 输入: s = "abcabcbb" 13 | 输出: 3 14 | 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 15 | ``` 16 | 17 | 示例 2: 18 | 19 | ``` 20 | 输入: s = "bbbbb" 21 | 输出: 1 22 | 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 23 | ``` 24 | 25 | 示例 3: 26 | 27 | ``` 28 | 输入: s = "pwwkew" 29 | 输出: 3 30 | 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 31 | 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 32 | ``` 33 | 34 | 示例 4: 35 | 36 | ``` 37 | 输入: s = "" 38 | 输出: 0 39 | ``` 40 | 41 | ## 滑动窗口 42 | 43 | ```go 44 | func lengthOfLongestSubstring(s string) int { 45 | if len(s) == 0 { 46 | return 0 47 | } 48 | hash := make(map[byte]bool) // 记录每个字符是否出现过 49 | var left, right, maxLen int = 0, 0, 0 50 | for right < len(s) { 51 | for hash[s[right]] { 52 | // 出现重复 左边界一直右移 直到不重复 53 | hash[s[left]] = false 54 | left++ 55 | } 56 | if right-left+1 > maxLen { 57 | maxLen = right - left + 1 58 | } 59 | hash[s[right]] = true 60 | right++ 61 | } 62 | return maxLen 63 | } 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/383. 赎金信.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "383. 赎金信" 3 | date: 2022-03-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 哈希] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 383. 赎金信 12 | 13 | 给你两个字符串:`ransomNote` 和 `magazine` ,判断 `ransomNote` 能不能由 `magazine` 里面的字符构成。 14 | 15 | 如果可以,返回 `true` ;否则返回 `false` 。 16 | 17 | `magazine` 中的每个字符只能在 `ransomNote` 中使用一次。 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:ransomNote = "a", magazine = "b" 23 | 输出:false 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:ransomNote = "aa", magazine = "ab" 30 | 输出:false 31 | ``` 32 | 33 | **示例 3:** 34 | 35 | ``` 36 | 输入:ransomNote = "aa", magazine = "aab" 37 | 输出:true 38 | ``` 39 | 40 | ## 哈希 41 | 42 | 只由小写字母构成,那就用数组代替 map 43 | 44 | ```go 45 | func canConstruct(ransomNote string, magazine string) bool { 46 | var hash [26]int 47 | for _, letter := range []byte(magazine) { 48 | hash[letter-'a']++ 49 | } 50 | for _, letter := range []byte(ransomNote) { 51 | hash[letter-'a']-- 52 | if hash[letter-'a'] < 0 { 53 | return false 54 | } 55 | } 56 | return true 57 | } 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/394. 字符串解码.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "394. 字符串解码" 3 | date: 2022-08-16 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 栈] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 394. 字符串解码 12 | 13 | `mid` 14 | 15 | image-20220816115637705 16 | 17 | ## 辅助栈 18 | 19 | image-20220816120055905 20 | 21 | ```go 22 | import "strconv" 23 | 24 | type node struct { 25 | prevRes string 26 | curMulti int 27 | } 28 | 29 | func decodeString(s string) string { 30 | stack := make([]node, 0) 31 | multi, tmpStr := 0, "" 32 | for i := 0; i < len(s); i++ { 33 | if '0' <= s[i] && s[i] <= '9' { 34 | // 累计数字 35 | num, _ := strconv.Atoi(string(s[i])) 36 | multi = multi*10 + num 37 | } else if s[i] == '[' { 38 | // 将之前的结果和这次的重复个数入栈 39 | stack = append(stack, node{prevRes: tmpStr, curMulti: multi}) 40 | // 清空 41 | multi, tmpStr = 0, "" 42 | } else if s[i] == ']' { 43 | // 出栈 结算 44 | curNode := stack[len(stack)-1] 45 | stack = stack[:len(stack)-1] 46 | prevRes := curNode.prevRes 47 | for j := 0; j < curNode.curMulti; j++ { 48 | prevRes += tmpStr 49 | } 50 | tmpStr = prevRes 51 | } else { 52 | // 字母 53 | tmpStr += string(s[i]) 54 | } 55 | } 56 | return tmpStr 57 | } 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/459. 重复的子字符串.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "459. 重复的子字符串" 3 | date: 2022-03-14 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 459. 重复的子字符串 12 | 13 | `easy` 14 | 15 | 给定一个非空的字符串 `s` ,检查是否可以通过由它的一个子串重复多次构成。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入: s = "abab" 21 | 输出: true 22 | 解释: 可由子串 "ab" 重复两次构成。 23 | ``` 24 | 25 | ## 枚举 26 | 27 | ![image-20220314204654222](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220314204654222.png) 28 | 29 | ```go 30 | func repeatedSubstringPattern(s string) bool { 31 | for i := 1; i <= len(s)/2; i++ { 32 | // i代表长度 33 | if len(s)%i == 0 { 34 | // 长度整除 35 | isMatch := true 36 | for j := i; j < len(s); j++ { 37 | // 判断之后的字符串是否可以由0到i-1的子串构成 38 | if s[j] != s[j-i] { 39 | isMatch = false 40 | break 41 | } 42 | } 43 | if isMatch { 44 | return true 45 | } 46 | } 47 | } 48 | return false 49 | } 50 | ``` 51 | 52 | ## KMP 53 | 54 | ![image-20220314212251267](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20220314212251267.png) 55 | 56 | ```go 57 | func getNext(s string) []int { 58 | next := make([]int, len(s)) // 0-i子串的最长公共前后缀 59 | next[0] = 0 60 | i := 0 // i指向前缀 61 | for j := 1; j < len(s); j++ { 62 | // j指向后缀 63 | for i > 0 && s[i] != s[j] { 64 | i = next[i-1] 65 | } 66 | if s[i] == s[j] { 67 | i++ 68 | } 69 | next[j] = i 70 | } 71 | return next 72 | } 73 | 74 | func repeatedSubstringPattern(s string) bool { 75 | if len(s) == 0 { 76 | return false 77 | } 78 | next := getNext(s) 79 | if next[len(s)-1] != 0 && len(s)%(len(s)-next[len(s)-1]) == 0 { 80 | return true 81 | } 82 | return false 83 | } 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/49. 字母异位词分组.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "28. 实现 strStr()" 3 | date: 2022-03-26 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 哈希] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 49. 字母异位词分组 12 | 13 | 给你一个字符串数组,请你将 **字母异位词** 组合在一起。可以按任意顺序返回结果列表。 14 | 15 | **字母异位词** 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"] 21 | 输出: [["bat"],["nat","tan"],["ate","eat","tea"]] 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入: strs = [""] 28 | 输出: [[""]] 29 | ``` 30 | 31 | **示例 3:** 32 | 33 | ``` 34 | 输入: strs = ["a"] 35 | 输出: [["a"]] 36 | ``` 37 | 38 | ## 哈希 39 | 40 | 由于互为字母异位词的两个字符串包含的字母相同,因此两个字符串中的**相同字母出现的次数一定是相同的**,故可以将每个字母出现的次数使用字符串表示,作为哈希表的键。 41 | 42 | 由于字符串只包含小写字母,因此对于每个字符串,可以使用长度为 26 的数组记录每个字母出现的次数。需要注意的是,在使用数组作为哈希表的键时,不同语言的支持程度不同,因此不同语言的实现方式也不同。 43 | 44 | ```go 45 | func groupAnagrams(strs []string) [][]string { 46 | hash := make(map[[26]int32][]string) 47 | for _, str := range strs { 48 | var count [26]int32 49 | for _, letter := range str { 50 | count[letter-'a']++ 51 | } 52 | hash[count] = append(hash[count], str) 53 | } 54 | res := make([][]string, 0, len(hash)) 55 | for _, v := range hash { 56 | res = append(res, v) 57 | } 58 | return res 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/5. 最长回文子串.md: -------------------------------------------------------------------------------- 1 | # 最长回文子串 2 | 3 | `mid` 4 | 5 | 给你一个字符串 s,找到 s 中最长的回文子串。 6 | 7 | 示例 1: 8 | 9 | ``` 10 | 输入:s = "babad" 11 | 输出:"bab" 12 | 解释:"aba" 同样是符合题意的答案。 13 | ``` 14 | 15 | 示例 2: 16 | 17 | ``` 18 | 输入:s = "cbbd" 19 | 输出:"bb" 20 | ``` 21 | 22 | ## 中心扩散法 23 | 24 | 从每一个位置出发,向两边扩散即可。遇到不是回文的时候结束。 25 | 26 | img 27 | 28 | ```go 29 | func longestPalindrome(s string) string { 30 | var maxLen, maxLeftIndex int = 0, 0 31 | for i := 0; i < len(s); i++ { 32 | leftIndex := i 33 | rightIndex := i 34 | // 寻找回文中心相同部分 35 | for leftIndex-1 >= 0 && s[leftIndex-1] == s[i] { 36 | // 往左扩散 直到遇到与i不相等的字符为止 37 | leftIndex-- 38 | } 39 | for rightIndex+1 < len(s) && s[rightIndex+1] == s[i] { 40 | // 往右扩散 直到遇到与i不相等的字符为止 41 | rightIndex++ 42 | } 43 | // 左右扩散 44 | for leftIndex-1 >= 0 && rightIndex+1 < len(s) && s[leftIndex-1] == s[rightIndex+1] { 45 | leftIndex-- 46 | rightIndex++ 47 | } 48 | if rightIndex-leftIndex+1 > maxLen { 49 | maxLen = rightIndex - leftIndex + 1 50 | maxLeftIndex = leftIndex 51 | } 52 | } 53 | return s[maxLeftIndex : maxLeftIndex+maxLen] 54 | } 55 | ``` 56 | 57 | ```python 58 | class Solution: 59 | def longestPalindrome(self, s: str) -> str: 60 | maxl,max_len,n = 0,0,len(s) 61 | for i in range(2*n-1): 62 | l,r = i//2,i//2+i%2 63 | while l>=0 and r < n and s[l]==s[r]: 64 | if r-l+1>max_len: 65 | maxl,max_len = l,r-l+1 66 | l-=1 67 | r+=1 68 | return s[maxl:maxl+max_len] 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/541. 反转字符串 II.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "541. 反转字符串 II" 3 | date: 2022-03-11 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串, 双指针, 模拟] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 541. 反转字符串 II 12 | 13 | 给定一个字符串 `s` 和一个整数 `k`,从字符串开头算起,每计数至 `2k` 个字符,就反转这 `2k` 字符中的前 `k` 个字符。 14 | 15 | - 如果剩余字符少于 `k` 个,则将剩余字符全部反转。 16 | - 如果剩余字符小于 `2k` 但大于或等于 `k` 个,则反转前 `k` 个字符,其余字符保持原样。 17 | 18 | **示例 1:** 19 | 20 | ``` 21 | 输入:s = "abcdefg", k = 2 22 | 输出:"bacdfeg" 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:s = "abcd", k = 2 29 | 输出:"bacd" 30 | ``` 31 | 32 | ## 双指针 + 模拟 33 | 34 | 没啥好说的 35 | 36 | ```go 37 | func reverse(b []byte, l, r int) []byte { 38 | for l <= r { 39 | b[l], b[r] = b[r], b[l] 40 | l++ 41 | r-- 42 | } 43 | return b 44 | } 45 | 46 | func reverseStr(s string, k int) string { 47 | b := []byte(s) 48 | curLen := 0 49 | for curLen < len(s) { 50 | if curLen+2*k > len(s) { 51 | if len(s)-curLen > k { 52 | b = reverse(b, curLen, curLen+k-1) 53 | } else { 54 | b = reverse(b, curLen, len(s)-1) 55 | } 56 | return string(b) 57 | } else { 58 | b = reverse(b, curLen, curLen+k-1) 59 | curLen += k * 2 60 | } 61 | } 62 | return string(b) 63 | } 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/6. Z 字型变换.md: -------------------------------------------------------------------------------- 1 | # Z 字型变换 2 | 3 | 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 4 | 5 | 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下: 6 | 7 | ``` 8 | P A H N 9 | A P L S I I G 10 | Y I R 11 | ``` 12 | 13 | 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR" 14 | 15 | ## 解 16 | 17 | 这一题没有什么算法思想,考察的是对程序控制的能力。 18 | 19 | ```go 20 | func convert(s string, numRows int) string { 21 | step := numRows*2 - 2 // 到达下一层要跳转的步长 22 | if step <= 0 { 23 | return s 24 | } 25 | result := make([]byte, 0) 26 | for i := 0; i < numRows; i++ { 27 | // 遍历每一层 28 | for j := i; j < len(s); j = j + step { 29 | // 控制步长来遍历一层中的每一个元素 30 | result = append(result, s[j]) 31 | row := j%step + 1 // j所在层数 以1为始 32 | if row > 1 && row <= numRows-1 && j+(numRows-row)*2 < len(s) { 33 | // 添加z型拐弯处的字母 34 | result = append(result, s[j+(numRows-row)*2]) 35 | } 36 | } 37 | } 38 | return string(result) 39 | } 40 | ``` 41 | 42 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/8. 字符串转换整数.md: -------------------------------------------------------------------------------- 1 | # 字符串转换整数 (atoi) 2 | 3 | 请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。 4 | 5 | 函数 myAtoi(string s) 的算法如下: 6 | 7 | - 读入字符串并丢弃无用的前导空格 8 | - 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。 9 | - 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。 10 | - 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。 11 | - 如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。 12 | - 返回整数作为最终结果。 13 | 14 | 注意: 15 | 16 | - 本题中的空白字符只包括空格字符 ' ' 。 17 | - 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。 18 | 19 | ## 题解 20 | 21 | 这道题真的好奇怪。。。 22 | 23 | ```go 24 | func myAtoi(s string) int { 25 | sign := 1 // 符号 默认为正 26 | index := 0 27 | for index < len(s) { 28 | // 去除前导空格 29 | if s[index] == ' ' { 30 | index++ 31 | continue 32 | } 33 | // 判断正负 34 | if s[index] == '+' { 35 | sign = 1 36 | index++ 37 | } else if s[index] == '-' { 38 | sign = -1 39 | index++ 40 | } 41 | break 42 | } 43 | result := 0 44 | for ; index < len(s); index++ { 45 | if s[index] >= '0' && s[index] <= '9' { 46 | result = result*10 + int(s[index]-'0') 47 | if sign*result > math.MaxInt32 { 48 | return math.MaxInt32 49 | } else if sign*result < math.MinInt32 { 50 | return math.MinInt32 51 | } 52 | } else { 53 | break 54 | } 55 | } 56 | return sign * result 57 | } 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/剑指 Offer 05. 替换空格.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 05. 替换空格" 3 | date: 2022-02-11 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 字符串] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 05. 替换空格 12 | 13 | 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:s = "We are happy." 19 | 输出:"We%20are%20happy." 20 | ``` 21 | 22 | ## 遍历添加 23 | 24 | ```go 25 | // 遍历添加 时间复杂度O(N),空间复杂度O(N) 26 | func replaceSpace(s string) string { 27 | b := make([]byte, 0) 28 | for i := 0; i < len(s); i++ { 29 | if s[i] == ' ' { 30 | b = append(b, []byte("%20")...) 31 | } else { 32 | b = append(b, s[i]) 33 | } 34 | } 35 | return string(b) 36 | } 37 | ``` 38 | 39 | ## 原地修改 40 | 41 | 扩充然后逆序填入 42 | 43 | **其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后再从后向前进行操作。** 44 | 45 | ```go 46 | // 原地修改 时间复杂度O(N),空间复杂度O(1) 47 | func replaceSpace(s string) string { 48 | b := []byte(s) 49 | length := len(b) 50 | spaceCount := 0 51 | // 计算空格数量 52 | for _, v := range b { 53 | if v == ' ' { 54 | spaceCount++ 55 | } 56 | } 57 | // 扩展原有切片 58 | tmp := make([]byte, spaceCount*2) 59 | b = append(b, tmp...) 60 | i := length - 1 // 指向原来最后一位 61 | j := len(b) - 1 // 指向现在最后一位 62 | // 从后向前填充 63 | for i >= 0 { 64 | if b[i] != ' ' { 65 | b[j] = b[i] 66 | i-- 67 | j-- 68 | } else { 69 | b[j] = '0' 70 | b[j-1] = '2' 71 | b[j-2] = '%' 72 | i-- 73 | j = j - 3 74 | } 75 | } 76 | return string(b) 77 | } 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/剑指 Offer 50. 第一个只出现一次的字符.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 50. 第一个只出现一次的字符 2 | 3 | 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。 4 | 5 | **示例 1:** 6 | 7 | ``` 8 | 输入:s = "abaccdeff" 9 | 输出:'b' 10 | ``` 11 | 12 | **示例 2:** 13 | 14 | ``` 15 | 输入:s = "" 16 | 输出:' ' 17 | ``` 18 | 19 | ## 哈希表 20 | 21 | 哈希表存放每个出现过字母的出现位置索引 22 | 23 | ```go 24 | func firstUniqChar(s string) byte { 25 | hash := make(map[byte][]int) 26 | for i := 0; i < len(s); i++ { 27 | hash[s[i]] = append(hash[s[i]], i) 28 | } 29 | resultWord := byte(' ') 30 | index := math.MaxInt 31 | for k, v := range hash { 32 | if len(v) == 1 && v[len(v)-1] < index { 33 | resultWord = k 34 | index = v[len(v)-1] 35 | } 36 | } 37 | return resultWord 38 | } 39 | ``` 40 | 41 | ## 不用哈希表 42 | 43 | 题目特性:26 个小写字母可以存在 `[26]int` 的数组中 44 | 45 | 先遍历一遍字符串,将其出现次数存储在数组中,在按字符串遍历一次,同时按字母查询数组,如果次数为 1 则返回。 46 | 47 | 更快一点。 48 | 49 | ```go 50 | func firstUniqChar2(s string) byte { 51 | var list [26]int 52 | length := len(s) 53 | for i := 0; i < length; i++ { 54 | list[s[i]-'a']++ 55 | } 56 | for i := 0; i < length; i++ { 57 | if list[s[i]-'a'] == 1 { 58 | return s[i] 59 | } 60 | } 61 | return ' ' 62 | } 63 | ``` 64 | 65 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/剑指 Offer 58 - I. 翻转单词顺序.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 58 - I. 翻转单词顺序 2 | 3 | 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。 4 | 5 | **示例 1:** 6 | 7 | ``` 8 | 输入: "the sky is blue" 9 | 输出: "blue is sky the" 10 | ``` 11 | 12 | **示例 2:** 13 | 14 | ``` 15 | 输入: " hello world! " 16 | 输出: "world! hello" 17 | 解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 18 | ``` 19 | 20 | **示例 3:** 21 | 22 | ``` 23 | 输入: "a good example" 24 | 输出: "example good a" 25 | 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。 26 | ``` 27 | 28 | ## 双指针 29 | 30 | image-20220222172141138 31 | 32 | image-20220222172149471 33 | 34 | ```go 35 | func reverseWords(s string) string { 36 | words := make([]string, 0) 37 | i, j := len(s)-1, len(s)-1 38 | for i >= 0 && j >= 0 { 39 | // j先移动到一个单词的右边界 40 | for j >= 0 && s[j] == ' ' { 41 | j-- 42 | } 43 | if j < 0 { 44 | break 45 | } 46 | i = j 47 | // i移动到一个单词的左边界 48 | for i >= 0 && s[i] != ' ' { 49 | i-- 50 | } 51 | words = append(words, s[i+1:j+1]) 52 | j = i 53 | } 54 | return strings.Join(words, " ") 55 | } 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/string/剑指 Offer 58 - II. 左旋转字符串.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 58 - II. 左旋转字符串 2 | 3 | `easy` 4 | 5 | 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。 6 | 7 | 请定义一个函数实现字符串左旋转操作的功能。 8 | 9 | 比如,输入字符串"abcdefg"和数字 2,该函数将返回左旋转两位得到的结果"cdefgab"。 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入: s = "abcdefg", k = 2 15 | 输出: "cdefgab" 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入: s = "lrloseumgh", k = 6 22 | 输出: "umghlrlose" 23 | ``` 24 | 25 | ## 语法糖 26 | 27 | ```go 28 | func reverseLeftWords(s string, n int) string { 29 | return s[n:] + s[:n] 30 | } 31 | ``` 32 | 33 | ## 三次倒转 34 | 35 | 三次反转即可得到所求答案,空间复杂度降低为 O(1),属于是原地旋转 36 | 37 | ```go 38 | // reverse 倒转字节数组 s将会被修改 39 | func reverse(s []byte) { 40 | n := len(s) 41 | for i := 0; i < n/2; i++ { 42 | // 交换头尾位置 43 | tmp := s[i] 44 | s[i] = s[n-i-1] 45 | s[n-i-1] = tmp 46 | } 47 | } 48 | 49 | // 三次倒转 50 | func reverseLeftWords2(s string, n int) string { 51 | bytes := []byte(s) 52 | reverse(bytes[:n]) // 左边部分转 53 | reverse(bytes[n:]) // 右边部分转 54 | reverse(bytes) // zheng'ti'z 55 | return string(bytes) 56 | } 57 | ``` -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/108. 将有序数组转换为二叉搜索树: -------------------------------------------------------------------------------- 1 | --- 2 | title: "108. 将有序数组转换为二叉搜索树" 3 | date: 2023-07-12 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 树, 对称性递归] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 108. 将有序数组转换为二叉搜索树 12 | 13 | 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 14 | 15 | 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 16 | 17 | 示例 1: 18 | 19 | ![img](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/btree1.jpg) 20 | 21 | 22 | 输入:nums = [-10,-3,0,5,9] 23 | 输出:[0,-3,9,-10,null,5] 24 | 解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案: 25 | 26 | ![img](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/btree2.jpg) 27 | 28 | ## 递归 29 | 30 | 总是选择中间位置左边的数字作为根节点 31 | 32 | ```go 33 | func sortedArrayToBST(nums []int) *TreeNode { 34 | var helper func(l,r int)*TreeNode 35 | helper = func(l,r int)*TreeNode { 36 | if l>r { 37 | return nil 38 | } 39 | mid := (l+r)>>1 40 | root := &TreeNode{Val: nums[mid]} 41 | root.Left = helper(l,mid-1) 42 | root.Right = helper(mid+1,r) 43 | return root 44 | } 45 | return helper(0,len(nums)-1) 46 | } 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/226. 翻转二叉树.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "226. 翻转二叉树" 3 | date: 2022-08-04 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 树, 对称性递归] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 226. 翻转二叉树 12 | 13 | `easy` 14 | 15 | 给你一棵二叉树的根节点 `root` ,翻转这棵二叉树,并返回其根节点。 16 | 17 | image-20220808113621930 18 | 19 | ## 递归 20 | 21 | 睿智题 22 | 23 | ```go 24 | func invertTree(root *TreeNode) *TreeNode { 25 | if root == nil { 26 | return nil 27 | } 28 | root.Left, root.Right = invertTree(root.Right), invertTree(root.Left) 29 | return root 30 | } 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/98. 验证二叉搜索树.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "98. 验证二叉搜索树" 3 | date: 2022-07-20 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法, 树, 对称性递归, 中序遍历] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 98. 验证二叉搜索树 12 | 13 | `mid` 14 | 15 | 给你一个二叉树的根节点 `root` ,判断其是否是一个有效的二叉搜索树。 16 | 17 | **有效** 二叉搜索树定义如下: 18 | 19 | - 节点的左子树只包含 **小于** 当前节点的数。 20 | - 节点的右子树只包含 **大于** 当前节点的数。 21 | - 所有左子树和右子树自身必须也是二叉搜索树。 22 | 23 | image-20220720155852513 24 | 25 | ## 递归 26 | 27 | 需要提供当前最小值和最大值 28 | 29 | ```go 30 | // 递归 31 | func isValidBST(root *TreeNode) bool { 32 | var help func(root *TreeNode, minVal, maxVal int) bool 33 | 34 | help = func(root *TreeNode, minVal, maxVal int) bool { 35 | if root == nil { 36 | return true 37 | } 38 | 39 | if root.Val <= minVal || root.Val >= maxVal { 40 | return false 41 | } 42 | 43 | return help(root.Left, minVal, root.Val) && help(root.Right, root.Val, maxVal) 44 | } 45 | 46 | return help(root, math.MinInt64, math.MaxInt64) 47 | } 48 | ``` 49 | 50 | ## 栈 + 中序遍历 51 | 52 | ```go 53 | func isValidBST(root *TreeNode) bool { 54 | stack := make([]*TreeNode, 0) 55 | lastNodeVal := math.MinInt64 56 | curNode := root 57 | 58 | for len(stack) != 0 || curNode != nil { 59 | if curNode != nil { 60 | stack = append(stack, curNode) 61 | curNode = curNode.Left 62 | } else { 63 | curNode = stack[len(stack)-1] 64 | stack = stack[:len(stack)-1] 65 | // 跟中序遍历的上一个节点值比较 66 | if curNode.Val <= lastNodeVal { 67 | return false 68 | } 69 | lastNodeVal = curNode.Val 70 | curNode = curNode.Right 71 | } 72 | } 73 | return true 74 | } 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 07. 重建二叉树.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 07. 重建二叉树" 3 | date: 2022-02-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,分治] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 07. 重建二叉树 12 | 13 | `mid` 14 | 15 | 输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。 16 | 17 | 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 18 | 19 | image-20220228193829120 20 | 21 | ## 分治 22 | 23 | image-20220228194014990 24 | 25 | 26 | 27 | ```go 28 | func buildTree(preorder []int, inorder []int) *TreeNode { 29 | hash := make(map[int]int) 30 | // 构建中序遍历的哈希表 31 | for i, val := range inorder { 32 | hash[val] = i 33 | } 34 | 35 | var bt func(preorder []int, inorder []int, offset int) *TreeNode 36 | bt = func(preorder []int, inorder []int, offset int) *TreeNode { 37 | // 为了方便哈希表查找 添加offset参数为相对0位置的偏移量 38 | if len(preorder) == 0 { 39 | return nil 40 | } 41 | root := TreeNode{Val: preorder[0]} // 找到根节点 42 | i := hash[root.Val] - offset // 找到根节点在中序遍历中的索引位置 43 | 44 | root.Left = bt(preorder[1:i+1], inorder[:i], offset) 45 | root.Right = bt(preorder[i+1:], inorder[i+1:], offset+i+1) 46 | return &root 47 | } 48 | root := bt(preorder, inorder, 0) 49 | return root 50 | } 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 26. 树的子结构.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 26. 树的子结构" 3 | date: 2022-02-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,对称性递归] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 26. 树的子结构 12 | 13 | `mid` 14 | 15 | 输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(约定空树不是任意一个树的子结构) 16 | 17 | B 是 A 的子结构, 即 A 中有出现和 B 相同的结构和节点值。 18 | 19 | 例如: 20 | 21 | 给定的树 A: 22 | 23 | ``` 24 | 3 25 | / \ 26 | 4 5 27 | / \ 28 | 1 2 29 | ``` 30 | 31 | 给定的树 B: 32 | 33 | ``` 34 | 4 35 | / 36 | 1 37 | ``` 38 | 39 | 返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。 40 | 41 | **示例 1:** 42 | 43 | ``` 44 | 输入:A = [1,2,3], B = [3,1] 45 | 输出:false 46 | ``` 47 | 48 | **示例 2:** 49 | 50 | ``` 51 | 输入:A = [3,4,5,1,2], B = [4,1] 52 | 输出:true 53 | ``` 54 | 55 | ## 对称性递归 56 | 57 | ```go 58 | // 从头结点开始 是不是子树 59 | func isSubStructureHelp(A *TreeNode, B *TreeNode) bool { 60 | if B == nil { 61 | return true 62 | } else if A == nil { 63 | // B不空A空 64 | return false 65 | } 66 | 67 | if A.Val == B.Val { 68 | return isSubStructureHelp(A.Left, B.Left) && isSubStructureHelp(A.Right, B.Right) 69 | } 70 | return false 71 | } 72 | 73 | func isSubStructure(A *TreeNode, B *TreeNode) bool { 74 | if A == nil || B == nil { 75 | return false 76 | } 77 | return isSubStructureHelp(A, B) || isSubStructure(A.Left, B) || isSubStructure(A.Right, B) 78 | } 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 27. 二叉树的镜像.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 27. 二叉树的镜像" 3 | date: 2022-02-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,对称性递归] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 27. 二叉树的镜像 12 | 13 | `mid` 14 | 15 | 请完成一个函数,输入一个二叉树,该函数输出它的镜像。 16 | 17 | 例如输入: 18 | 19 | ``` 20 | 4 21 | / \ 22 | 2 7 23 | / \ / \ 24 | 1 3 6 9 25 | ``` 26 | 27 | 镜像输出: 28 | 29 | ``` 30 | 4 31 | / \ 32 | 7 2 33 | / \ / \ 34 | 9 6 3 1 35 | ``` 36 | 37 | **示例 1:** 38 | 39 | ``` 40 | 输入:root = [4,2,7,1,3,6,9] 41 | 输出:[4,7,2,9,6,3,1] 42 | ``` 43 | 44 | ## 递归 45 | 46 | ```go 47 | // 递归 48 | func mirrorTree(root *TreeNode) *TreeNode { 49 | if root == nil { 50 | return nil 51 | } 52 | 53 | left := mirrorTree(root.Left) 54 | right := mirrorTree(root.Right) 55 | 56 | root.Left = right 57 | root.Right = left 58 | return root 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 28. 对称的二叉树.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 28. 对称的二叉树" 3 | date: 2022-02-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,对称性递归] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 28. 对称的二叉树 12 | 13 | `mid` 14 | 15 | 请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。 16 | 17 | 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 18 | 19 | ``` 20 | 1 21 | / \ 22 | 2 2 23 | / \ / \ 24 | 3 4 4 3 25 | ``` 26 | 27 | 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 28 | 29 | ``` 30 | 1 31 | / \ 32 | 2 2 33 | \ \ 34 | 3 3 35 | ``` 36 | 37 | ## 递归 38 | 39 | ![Picture1.png](https://pic.leetcode-cn.com/ebf894b723530a89cc9a1fe099f36c57c584d4987b080f625b33e228c0a02bec-Picture1.png) 40 | 41 | ```go 42 | func isSymmetric(root *TreeNode) bool { 43 | if root == nil { 44 | return true 45 | } 46 | 47 | return isSymmetricHelp(root.Left, root.Right) 48 | } 49 | 50 | // 判断两棵树是否镜像 51 | func isSymmetricHelp(A *TreeNode, B *TreeNode) bool { 52 | if A == nil && B == nil { 53 | return true 54 | } else if A == nil || B == nil { 55 | // 若一个为空一个不为空 56 | return false 57 | } 58 | 59 | if A.Val == B.Val && isSymmetricHelp(A.Left, B.Right) && isSymmetricHelp(A.Right, B.Left) { 60 | return true 61 | } 62 | return false 63 | } 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 32 - II. 从上到下打印二叉树 II.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 32 - II. 从上到下打印二叉树 II" 3 | date: 2022-02-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,对称性递归] 7 | categories: [刷题] 8 | hiddenFromHomePage: true 9 | --- 10 | 11 | # 剑指 Offer 32 - II. 从上到下打印二叉树 II 12 | 13 | `easy` 14 | 15 | 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。 16 | 17 | 例如: 18 | 19 | 给定二叉树: `[3,9,20,null,null,15,7]`, 20 | 21 | ``` 22 | 3 23 | / \ 24 | 9 20 25 | / \ 26 | 15 7 27 | ``` 28 | 29 | 返回其层次遍历结果: 30 | 31 | ``` 32 | [ 33 | [3], 34 | [9,20], 35 | [15,7] 36 | ] 37 | ``` 38 | 39 | ## 解 40 | 41 | 记录一下就好了 42 | 43 | ```go 44 | func levelOrder(root *TreeNode) [][]int { 45 | if root == nil { 46 | return [][]int{} 47 | } 48 | result := make([][]int, 0) 49 | queue := make([]*TreeNode, 0) 50 | queue = append(queue, root) 51 | curCount := 1 52 | curLevel := 0 53 | nextCount := 0 54 | for len(queue) != 0 { 55 | curNodes := make([]int, 0) 56 | for curCount > 0 { 57 | curNode := queue[0] 58 | queue = queue[1:] 59 | curNodes = append(curNodes, curNode.Val) 60 | if curNode.Left != nil { 61 | queue = append(queue, curNode.Left) 62 | nextCount++ 63 | } 64 | if curNode.Right != nil { 65 | queue = append(queue, curNode.Right) 66 | nextCount++ 67 | } 68 | curCount-- 69 | } 70 | result = append(result, curNodes) 71 | curCount = nextCount 72 | nextCount = 0 73 | curLevel++ 74 | } 75 | return result 76 | } 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 32 - III. 从上到下打印二叉树 III.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer 32 - III. 从上到下打印二叉树 III 2 | 3 | `mid` 4 | 5 | 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。 6 | 7 | 例如: 8 | 给定二叉树: `[3,9,20,null,null,15,7]`, 9 | 10 | ``` 11 | 3 12 | / \ 13 | 9 20 14 | / \ 15 | 15 7 16 | ``` 17 | 18 | 返回其层次遍历结果: 19 | 20 | ``` 21 | [ 22 | [3], 23 | [20,9], 24 | [15,7] 25 | ] 26 | ``` 27 | 28 | ## 解 29 | 30 | 隔一个倒序一下 31 | 32 | ```go 33 | func levelOrder(root *TreeNode) [][]int { 34 | if root == nil { 35 | return [][]int{} 36 | } 37 | result := make([][]int, 0) 38 | queue := make([]*TreeNode, 0) 39 | queue = append(queue, root) 40 | curCount := 1 41 | curLevel := 0 42 | nextCount := 0 43 | isAscending := true 44 | for len(queue) != 0 { 45 | curNodes := make([]int, 0) 46 | for curCount > 0 { 47 | curNode := queue[0] 48 | queue = queue[1:] 49 | curNodes = append(curNodes, curNode.Val) 50 | if curNode.Left != nil { 51 | queue = append(queue, curNode.Left) 52 | nextCount++ 53 | } 54 | if curNode.Right != nil { 55 | queue = append(queue, curNode.Right) 56 | nextCount++ 57 | } 58 | curCount-- 59 | } 60 | if !isAscending { 61 | // 倒序 62 | reversedNodes := make([]int, 0) 63 | for i := len(curNodes) - 1; i >= 0; i-- { 64 | reversedNodes = append(reversedNodes, curNodes[i]) 65 | } 66 | result = append(result, reversedNodes) 67 | } else { 68 | result = append(result, curNodes) 69 | } 70 | curCount = nextCount 71 | nextCount = 0 72 | curLevel++ 73 | isAscending = !isAscending 74 | } 75 | return result 76 | } 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 33. 二叉搜索树的后序遍历序列.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 33. 二叉搜索树的后序遍历序列" 3 | date: 2022-03-03 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,分治] 7 | categories: [刷题] 8 | --- 9 | 10 | # 剑指 Offer 33. 二叉搜索树的后序遍历序列 11 | 12 | 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 `true`,否则返回 `false`。假设输入的数组的任意两个数字都互不相同。 13 | 14 | 参考以下这颗二叉搜索树: 15 | 16 | ``` 17 | 5 18 | / \ 19 | 2 6 20 | / \ 21 | 1 3 22 | ``` 23 | 24 | **示例 1:** 25 | 26 | ``` 27 | 输入: [1,6,3,2,5] 28 | 输出: false 29 | ``` 30 | 31 | **示例 2:** 32 | 33 | ``` 34 | 输入: [1,3,2,6,5] 35 | 输出: true 36 | ``` 37 | 38 | ## 递归分治 39 | 40 | Picture1.png 41 | 42 | image-20220303184653473 43 | 44 | - 逻辑 45 | 46 | - 从后向前遍历,寻找第一个小于根节点的元素下标 i(这样可以保证右子树均大于根节点) 47 | 48 | - 对左子树正确性进行判断,即从 i 向前进行遍历,若发现大于根节点的值,则判断不是搜索二叉树,返回 false 49 | 50 | - 对左右子树递归 51 | 52 | ```go 53 | func verifyPostorder(postorder []int) bool { 54 | if len(postorder) == 0 { 55 | return true 56 | } 57 | rootVal := postorder[len(postorder)-1] 58 | var i int 59 | for i = len(postorder) - 1; i >= 0; i-- { 60 | // 找到第一个小于rootVal的下标 61 | if postorder[i] < rootVal { 62 | break 63 | } 64 | } 65 | 66 | for j := i; j >= 0; j-- { 67 | if postorder[j] > rootVal { 68 | return false 69 | } 70 | } 71 | 72 | return verifyPostorder(postorder[:i+1]) && verifyPostorder(postorder[i+1:len(postorder)-1]) 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer 55 - II. 平衡二叉树.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "剑指 Offer 55 - II. 平衡二叉树" 3 | date: 2022-02-27 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [算法,树,回溯] 7 | categories: [刷题] 8 | --- 9 | 10 | # 剑指 Offer 55 - II. 平衡二叉树 11 | 12 | `easy` 13 | 14 | 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过 1,那么它就是一棵平衡二叉树。 15 | 16 | image-20220227212454992 17 | 18 | ## 后序遍历(DFS) 19 | 20 | ```go 21 | package tree 22 | 23 | func max(a, b int) int { 24 | if a > b { 25 | return a 26 | } 27 | return b 28 | } 29 | 30 | func abs(a int) int { 31 | if a < 0 { 32 | return -a 33 | } 34 | return a 35 | } 36 | 37 | func isBalanced(root *TreeNode) bool { 38 | var bp func(root *TreeNode) (int, bool) 39 | bp = func(root *TreeNode) (int, bool) { 40 | // 返回高度, 是否是平衡二叉树 41 | if root == nil { 42 | return 0, true 43 | } 44 | d1, b1 := bp(root.Left) 45 | d2, b2 := bp(root.Right) 46 | 47 | if b1 && b2 && abs(d1-d2) <= 1 { 48 | return max(d1, d2)+1, true 49 | } 50 | return max(d1, d2)+1, false 51 | } 52 | _, res := bp(root) 53 | return res 54 | 55 | } 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /content/posts/专业/刷题/tree/剑指 Offer32 - I. 从上到下打印二叉树.md: -------------------------------------------------------------------------------- 1 | # 剑指 Offer32 - I. 从上到下打印二叉树.md 2 | 3 | `easy` 4 | 5 | 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。 6 | 7 | 例如: 8 | 给定二叉树: `[3,9,20,null,null,15,7]`, 9 | 10 | ``` 11 | 3 12 | / \ 13 | 9 20 14 | / \ 15 | 15 7 16 | ``` 17 | 18 | 返回: 19 | 20 | ``` 21 | [3,9,20,15,7] 22 | ``` 23 | 24 | ## 队列 25 | 26 | 就是一个层序遍历 27 | 28 | ```go 29 | // 队列实现层序遍历 30 | func levelOrder(root *TreeNode) []int { 31 | if root == nil { 32 | return []int{} 33 | } 34 | queue := make([]*TreeNode, 0) 35 | queue = append(queue, root) 36 | result := make([]int, 0) 37 | for len(queue) != 0 { 38 | curNode := queue[0] 39 | queue = queue[1:] 40 | result = append(result, curNode.Val) 41 | if curNode.Left != nil { 42 | queue = append(queue, curNode.Left) 43 | } 44 | if curNode.Right != nil { 45 | queue = append(queue, curNode.Right) 46 | } 47 | } 48 | return result 49 | } 50 | ``` 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /content/posts/专业/工具/Tmux.md: -------------------------------------------------------------------------------- 1 | # Tmux 2 | -------------------------------------------------------------------------------- /content/posts/专业/工具/Untitled.loom: -------------------------------------------------------------------------------- 1 | { 2 | "model": { 3 | "columns": [ 4 | { 5 | "id": "c12c1b5c-6666-4c8d-8296-577983cd9615", 6 | "sortDir": "default", 7 | "isVisible": true, 8 | "width": "140px", 9 | "type": "text", 10 | "numberPrefix": "", 11 | "numberSuffix": "", 12 | "numberSeparator": "", 13 | "content": "New Column", 14 | "numberFormat": "number", 15 | "currencyType": "USD", 16 | "dateFormat": "mmddyyyy", 17 | "dateFormatSeparator": "-", 18 | "hour12": true, 19 | "includeTime": false, 20 | "shouldWrapOverflow": true, 21 | "tags": [], 22 | "calculationType": "none", 23 | "aspectRatio": "unset", 24 | "horizontalPadding": "unset", 25 | "verticalPadding": "unset", 26 | "frontmatterKey": null 27 | } 28 | ], 29 | "rows": [ 30 | { 31 | "id": "8d58804c-a1c0-4247-8c70-7abe09184d51", 32 | "index": 0, 33 | "sourceId": null, 34 | "creationDateTime": "2024-04-19T07:45:15.820Z", 35 | "lastEditedDateTime": "2024-04-19T07:45:15.820Z", 36 | "cells": [ 37 | { 38 | "id": "546c4cc2-dcc2-4daf-9dbe-a666c93b1e3b", 39 | "columnId": "c12c1b5c-6666-4c8d-8296-577983cd9615", 40 | "content": "", 41 | "hasValidFrontmatter": null 42 | } 43 | ] 44 | } 45 | ], 46 | "filters": [], 47 | "sources": [], 48 | "settings": { 49 | "numFrozenColumns": 1, 50 | "showCalculationRow": true 51 | }, 52 | "externalRowOrder": [] 53 | }, 54 | "pluginVersion": "8.15.12" 55 | } -------------------------------------------------------------------------------- /content/posts/专业/工具/版本管理/gerrit.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Gerrit 3 | date: 2023-8-3 4 | draft: false 5 | author: MelonCholi 6 | tags: 7 | - 快速入门 8 | - 版本管理 9 | - CS 10 | categories: 11 | - 工具 12 | aliases: 13 | - Gerrit 14 | date created: 24-04-10 09:58 15 | date modified: 24-04-10 16:56 16 | --- 17 | 18 | # Gerrit 19 | 20 | Gerrit 是建立在 Git 版本控制系统之上并且基于 Web 的一个免费开源的轻量级代码审查工具。 21 | 22 | 作为开发者和 Git 之间的一层屏障,不允许直接将本地修改内容同步到远程仓库中。 23 | 24 | 与 Jenkins 集成后,可以在每次提交代码后,人工审核代码前,通过 Jenkins 任务自动运行单元测试、构建以及自动化测试,如果 Jenkins 任务失败,会自动打回本次提交。 25 | 26 | 一般 Git、Gerrit 和 Jenkins 集成后的使用流程 27 | 28 | 1. 开发者提交代码到 Gerrit 29 | 2. 触发对应的 Jenkins 任务,通过以后 Verified 加 1 30 | 3. 人工审核,审核通过后 code review 加 2,触发对应的 Jenkins 任务 31 | 4. 通过以后确认本次提交,Gerrit 执行与 Git 仓库的代码同步操作 32 | 5. 代码进入 Git 仓库 33 | 34 | img 35 | -------------------------------------------------------------------------------- /content/posts/博物/GeoGuessr 与图寻/GeoGuessr 与图寻.md: -------------------------------------------------------------------------------- 1 | --- 2 | obsidianUIMode: preview 3 | --- 4 | # GeoGuessr 与图寻 Overview 5 | 6 | ```ccard 7 | type: folder_brief_live 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /content/posts/博物/GeoGuessr 与图寻/指示牌.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "图寻 - 指示牌" 3 | date: 2023-12-03 4 | author: MelonCholi 5 | draft: false 6 | tags: [图寻] 7 | categories: [其他] 8 | --- 9 | 10 | # 指示牌 11 | 12 | ## 简述 13 | 14 | 全世界指示牌可以被大致分为两种,黄色菱形和红白三角。 15 | 16 | ![10 Useful Maps-1.png](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/1682740439259-0a95fbfc-0d3f-4d5a-9562-d3b987d0da06.png) 17 | 18 | 可以看到,美洲大陆、澳洲、爱尔兰、东南亚大部分地区和日本使用的都是黄色菱形。而欧洲、非洲和南亚都是红白三角。 19 | 20 | ### 让行指示牌 21 | 22 | 在**欧洲**,让行指示牌是非常常见的,基本上在每个路口都会有。一般来说,有几种特殊的样式。 23 | 24 | #### 黄色填涂 25 | 26 | 在这种让行指示牌中,中间是黄色,而不是白色。在**芬兰、瑞典、冰岛、波兰、北马其顿和希腊**可以看到。据说在斯洛文尼亚也有,但是没有验证过。 27 | 28 | 所以,如果看到黄色的填涂,可以优先考虑这些国家,可以缩小范围,进一步观察线、电线杆等等。 29 | 30 | #### 没有白边 31 | 32 | 在普通的让行指示牌上,红色边缘的外围会有一圈白色的细边。 33 | 34 | 但是,有些国家是没有这圈白边的,最外层的边就是红色。他们是**西班牙**和**爱沙尼亚**。 35 | 36 | ![image-20230628003629713](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230628003629713.png) 37 | 38 | #### 加粗红边 39 | 40 | 在**拉脱维亚**,虽然是正常白边和红边的设计,但是红边被加粗了。 41 | 42 | ![image-20230628004104400](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/image-20230628004104400.png) 43 | 44 | ### 限速指示牌 45 | 46 | 限速指示牌大部分都长的一样。 47 | 48 | 在**芬兰、瑞典、冰岛、北马其顿和希腊**,限速牌**中间是黄色**,而不是白色。 49 | 50 | 有时,斯洛文尼亚和克罗地亚也会出现,极少情况下其他国家会出现。 51 | 52 | image-20230628004150330 53 | 54 | ## 指示牌背面 55 | 56 | 主要分为两种,灰色和黑色,也有很少见的绿色。 57 | 58 | ### 南美洲 59 | 60 | 只有**巴西**和**秘鲁**的指示牌背后是**黑色**的。这是分辨巴西的一大方法。如果知道你在南美洲,且指示牌背后是黑色的,综合考虑这两个国家非常不同的环境,即可得到正确的国家。 61 | 62 | ### 欧洲 63 | 64 | 在欧洲,最常有**黑色**牌背的国家是**意大利,罗马尼亚,和阿尔巴尼亚**。同时,德国,瑞典,芬兰等国家也会出现黑色的牌背,但是因为这些国家都比较有特点,所以不如前三者有用。 65 | 66 | ### 绿色 67 | 68 | 如果你知道你在加拿大,而且你看到背面是绿色的指示牌,那么你将在不列颠哥伦比亚省,这是加拿大唯一一个使用绿色背面指示牌的省份。但是需要注意的是并不是所有 BC 牌子的背面都是绿色的,不能看到一个正常背面的牌子就排除 BC。 -------------------------------------------------------------------------------- /content/posts/博物/中世纪.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 未命名 3 | date: 2024-04-24 4 | author: CoengFan 5 | draft: false 6 | tags: [历史] 7 | categories: 8 | - 博物 9 | date created: 24-04-24 12:22 10 | date modified: 24-04-24 12:29 11 | --- 12 | 13 | # 中世纪 14 | -------------------------------------------------------------------------------- /content/posts/博物/双拼.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "双拼" 3 | date: 2022-12-28 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [奇怪的东东] 8 | --- 9 | 10 | # 双拼 11 | 12 | 以小鹤为例 13 | 14 | ![img](https://markdown-1303167219.cos.ap-shanghai.myqcloud.com/hejp.png) 15 | 16 | ## 口诀 17 | 18 | 秋闱软月云梳翅,松拥黛粉更航安 19 | 20 | 快莺两望奏夏蛙,撇草追鱼滨鸟眠 21 | 22 | | Qiu | Wei | Ruan | T_ue_ve | Yun | U_shu | I_chi | Song_iong | Dai | Fen | Geng | Hang | J_an | 23 | | ---- | ---- | ---- | ------- | ---- | ----- | ----- | --------- | ---- | ---- | ---- | ---- | ---- | 24 | | 秋 | 闱 | 软 | 月 | 云 | 梳 | 翅 | 松 拥 | 黛 | 粉 | 更 | 航 | 安 | 25 | 26 | | Kuai_ing | Liang_uang | Zou | Xia_ua | Pie | Cao | V_zhui_v | Bin | Niao | Mian | 27 | | -------- | ---------- | ---- | ------ | ---- | ---- | -------- | ---- | ---- | ---- | 28 | | 快 莺 | 两 望 | 奏 | 夏 蛙 | 撇 | 草 | 追 鱼 | 滨 | 鸟 | 眠 | 29 | 30 | ## 微软输入法切换 31 | 32 | 新建 bat 文件 33 | 34 | ```bat 35 | @echo off 36 | 37 | set Mainkey=HKCU\SOFTWARE\Microsoft\InputMethod\Settings\CHS 38 | for /f %%i in ('reg query %MainKey% /v "Enable Double Pinyin" ^| findstr /i "0x1"') do (set flg=%%i) 39 | if not defined flg ( 40 | reg add %MainKey% /v "Enable Double Pinyin" /t REG_DWORD /d 0x1 /f 41 | echo 已经切换到双拼 42 | (echo 已经切换到双拼 43 | echo 5秒后自动关闭)|msg %username% /time:5 44 | ) else ( 45 | reg add %MainKey% /v "Enable Double Pinyin" /t REG_DWORD /d 0x0 /f 46 | (echo 已经切换到全拼 47 | echo 1秒后自动关闭)|msg %username% /time:1 48 | ) 49 | ``` 50 | 51 | 注意:以 ANSI 格式保存 52 | 53 | 再添加一个快捷方式即可 54 | 55 | -------------------------------------------------------------------------------- /content/posts/音乐/教程链接.md: -------------------------------------------------------------------------------- 1 | --- 2 | draft: true 3 | --- 4 | 5 | # 教程链接 6 | 7 | 乐理 101:https://zhuanlan.zhihu.com/p/24538434 8 | 9 | 日文教材翻译总整理:https://www.jianshu.com/p/61f9a441c8f5 10 | 11 | - 理结与悠的作曲入门讲座:https://www2.jianshu.com/nb/22906125 12 | - 作曲法:https://www.jianshu.com/p/9b2e48e10ec7 13 | 14 | 编曲二三事:https://www.kdocs.cn/l/cnem1qq4L4Kj?openfrom=docs 15 | 16 | 吉他和弦琶音形状和公式汇总:https://www.bilibili.com/video/BV1XL4y1e73L -------------------------------------------------------------------------------- /content/posts/音乐/音频线材详解.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "音频线材详解" 3 | date: 2024-02-10 4 | draft: false 5 | author: "MelonCholi" 6 | tags: [] 7 | categories: [音乐] 8 | --- 9 | 10 | # 音频线材详解 11 | 12 | ![img](https://pic4.zhimg.com/80/v2-9790b203fed5d752b0de71d4ec502213_1440w.webp) 13 | 14 | ## 平衡与非平衡 15 | 16 | - **非平衡信号线** 有更大的可能性引入杂音和干扰。如果你切开一条非平衡信号线,里面有 2 条线:1 条导体和 1 条地线。 17 | - **平衡型号线**就刚好相反,它是设计用来消除杂音和干扰的,它通过增加一条导体来实现:里面有 2 条导体和 1 条地线。通过多出来的第二条导体,两条导体上的杂音都被消除了。 18 | 19 | 一根平衡信号线就能保证是平衡连接嘛? 20 | 21 | 不行!谨记一点:你要保持平衡连接就必须**保证整个回路上都是平衡信号**。总结就是如下: 22 | 23 | - 你设备上的输出 24 | - 线材 25 | - 线材的输入端(例如你的混音器或者麦克风) 26 | 27 | 只要有上面其中一个是非平衡信号,那么你的连接就是非平衡连接。 28 | 29 | 如果你的设备是下面这样的,你的设备就是平衡信号: 30 | 31 | - 它有 XLR 输出或者输入。 32 | - 你的设备上有写或者说明书有写。 33 | 34 | 例如:麦克风,某些混合器,扩音系统,某些带 XLR 输出的专业设备和合成器(例如罗兰 Jupiter 8 等等) 35 | 36 | 下面这些情况,你的设备是非平衡的: 37 | 38 | - 它是吉他或者贝斯 39 | - 它是 3.5 单声道或者双声道输出 40 | - 它是 RCA 输入或者输出 41 | 42 | 很多只带有 6.35mm 输出的设备都是非平衡的。如果它没有任何指引的话,通常也是非平衡信号。 -------------------------------------------------------------------------------- /push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # to install textlint, run the following command 4 | # npm install textlint --global 5 | # npm install textlint-rule-ja-space-between-half-and-full-width --global 6 | cd ./content/posts/ || exit 7 | textlint --fix . 8 | cd ../.. 9 | 10 | date=$(date "+%Y-%m-%d %H:%m") 11 | git add * 12 | git commit -m "$date update" 13 | git push 14 | -------------------------------------------------------------------------------- /resources/_gen/assets/scss/css/style.scss_d75fd08668b4bae707167bbce4d8ca46.json: -------------------------------------------------------------------------------- 1 | {"Target":"css/style.min.css","MediaType":"text/css","Data":{}} -------------------------------------------------------------------------------- /resources/_gen/assets/scss/notes/book.scss_50fc8c04e12a2f59027287995557ceff.json: -------------------------------------------------------------------------------- 1 | {"Target":"book.min.82c5dbd23447cee0b4c2aa3ed08ce0961faa40e1fa370eee4f8c9f02e0d46b5f.css","MediaType":"text/css","Data":{"Integrity":"sha256-gsXb0jRHzuC0wqo+0Izglh+qQOH6Nw7uT4yfAuDUa18="}} -------------------------------------------------------------------------------- /resources/_gen/assets/scss/notes/css/style.scss_d75fd08668b4bae707167bbce4d8ca46.json: -------------------------------------------------------------------------------- 1 | {"Target":"css/style.min.css","MediaType":"text/css","Data":{}} -------------------------------------------------------------------------------- /resources/_gen/assets/scss/notes/posts/css/style.scss_d75fd08668b4bae707167bbce4d8ca46.json: -------------------------------------------------------------------------------- 1 | {"Target":"css/style.min.css","MediaType":"text/css","Data":{}} --------------------------------------------------------------------------------