<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://blueberry-universe.cn/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <atom:link href="https://blueberry-universe.cn/rss.xml" rel="self" type="application/rss+xml"/>
    <title>酷酷的算法</title>
    <link>https://blueberry-universe.cn/</link>
    <description>我想帮助 1666 个学习计算机的小伙伴变得更好!</description>
    <language>zh-CN</language>
    <pubDate>Sun, 19 Jul 2026 16:34:54 GMT</pubDate>
    <lastBuildDate>Sun, 19 Jul 2026 16:34:54 GMT</lastBuildDate>
    <generator>@vuepress/plugin-feed</generator>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <item>
      <title>蓝莓程序岛</title>
      <link>https://blueberry-universe.cn/</link>
      <guid>https://blueberry-universe.cn/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">蓝莓程序岛</source>
      <description>蓝莓程序岛

欢迎关注我的微信公众号：蓝莓程序岛
我想帮助 1666 个学习计算机的小伙伴变得更好 ~
作者：蓝莓
本站地址：https://blueberry-universe.cn/

感谢你能来，我们一起加油呀 ~
本站内容










优秀博客推荐

小林coding 图解网络、图解系统、图解MySQL、图解Redis、Java 后端面...</description>
      <content:encoded><![CDATA[
<blockquote>
<p>欢迎关注我的微信公众号：蓝莓程序岛</p>
<p>我想帮助 1666 个学习计算机的小伙伴变得更好 ~</p>
<p>作者：蓝莓</p>
<p>本站地址：<a href="https://blueberry-universe.cn/" target="_blank" rel="noopener noreferrer">https://blueberry-universe.cn/</a></p>
</blockquote>
<p>感谢你能来，我们一起加油呀 ~</p>
<h2>本站内容</h2>
<ul>
<li><a href="/%E8%93%9D%E8%8E%93%E9%9A%8F%E4%BE%BF%E6%89%AF/" target="_blank">蓝莓随便扯</a></li>
<li><a href="/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" target="_blank">操作系统</a></li>
<li><a href="/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/" target="_blank">计算机网络</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/" target="_blank">力扣刷题</a></li>
<li><a href="/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/" target="_blank">分布式系统</a></li>
<li><a href="/Pythoner/" target="_blank">Pythoner</a></li>
<li><a href="/Java/" target="_blank">Java</a></li>
<li><a href="/Golang/" target="_blank">Golang</a></li>
</ul>
<h2>优秀博客推荐</h2>
<ul>
<li><a href="https://xiaolincoding.com/" target="_blank" rel="noopener noreferrer">小林coding</a> 图解网络、图解系统、图解MySQL、图解Redis、Java 后端面试题</li>
<li><a href="https://fasionchan.com/" target="_blank" rel="noopener noreferrer">小菜学编程</a> 学Python、其他杂七杂八的</li>
<li><a href="https://distsys.cn" target="_blank" rel="noopener noreferrer">木鸟杂记</a> 一个学习分布式系统的论坛</li>
<li><a href="https://javaguide.cn/" target="_blank" rel="noopener noreferrer">JavaGuide</a> Java 面试可参考</li>
</ul>
<h2>优秀图书推荐</h2>
<p>在这里推荐的这些书有一部分是我看过的，还有些是我没看过但是打算看的。这些图书应该都是非常经典的学习资料了，希望对你有帮助。</p>
<h3>1、操作系统</h3>
<ul>
<li>《程序员的自我修养 - 链接、装载和库》</li>
<li>《操作系统真象还原》</li>
<li>《深入理解计算机系统》</li>
</ul>
<h3>2、Java</h3>
<p><strong>Java 编程</strong></p>
<ul>
<li>《Head First Java》新手入门</li>
<li>《Java 核心技术 卷1 基础知识》新手入门</li>
<li>《Java8 实战》 Java8 的新特性讲的最全最仔细的</li>
<li>《Effective Java》 大量的 Java 编程实践 Java 之父推荐</li>
</ul>
<p><strong>虚拟机</strong></p>
<ul>
<li>《深入理解 Java 虚拟机》 进阶</li>
</ul>
<p><strong>并发编程</strong></p>
<ul>
<li>《Java并发编程实战》 系统全面的介绍了Java的并发，如何设计支持并发的数据结构，以及如何编写正确的并发程序</li>
<li>《实战Java高并发程序设计》比上一本更新，容易读</li>
</ul>
<p><strong>设计模式</strong></p>
<ul>
<li>《Head First 设计模式》</li>
</ul>
<p><strong>工具类</strong></p>
<ul>
<li>《Maven 实战》</li>
</ul>
<p><strong>性能优化</strong></p>
<ul>
<li>《Java性能权威指南》</li>
</ul>
<p><strong>单元测试</strong></p>
<ul>
<li>《有效的单元测试》</li>
</ul>
<p><strong>并发编程补充</strong></p>
<ul>
<li>《Java多线程编程核心技术》实战</li>
<li>《Java并发编程艺术》 理论</li>
</ul>
<p><strong>个人修养</strong></p>
<ul>
<li>《重构：改善既有代码的设计》</li>
<li>《代码整洁之道》</li>
<li>《程序员的职业素养》</li>
</ul>
<h3>3、数据库</h3>
<p><strong>MySQL</strong></p>
<ul>
<li>《MySQL必知必会》 入门</li>
<li>《高性能MySQL》 进阶</li>
<li>《MySQL技术内幕：InnoDB储存引擎》 MySQL 底层</li>
</ul>
<p><strong>Redis</strong></p>
<ul>
<li>《Redis 实战》 本书深入浅出地介绍了Redis的5种数据类型，并通过多个实用示例展示了Redis的用法，讲述了Redis的优化方法以及扩展方法。</li>
<li>《Redis设计与实现》 Redis 内部深入剖析</li>
</ul>
<h3>4、Kafka</h3>
<ul>
<li>《Kafka权威指南》 入门</li>
<li>《深入理解Kafka：核心设计与实践原理》 进阶</li>
<li>《Apache Kafka实战》 进阶</li>
<li>《Kafka技术内幕》 进阶</li>
</ul>
<h3>5、Spring</h3>
<p><strong>Spring</strong></p>
<ul>
<li>《Spring实战》 Redis 底层原理</li>
<li>《精通Spring 4.x ――企业应用开发实战》</li>
</ul>
<p><strong>Spring Boot</strong></p>
<ul>
<li>《SpringBoot实战》</li>
<li>《JavaEE开发的颠覆者：Spring Boot实战》</li>
<li>《SpringBoot揭秘：快速构建微服务体系》</li>
</ul>
<h3>6、操作系统</h3>
<p><strong>从零实现系列</strong></p>
<ul>
<li>《操作系统真象还原》 看过，作者讲的比较幽默一些，语言平易近人</li>
<li>《30天自制操作系统》 没看过，听说这也是一本很不错的书</li>
</ul>
<p><strong>拓展类的小书</strong></p>
<ul>
<li>《Linux 是怎样工作的》</li>
<li>《程序是怎样跑起来的》</li>
<li>《计算机是怎样跑起来的》</li>
<li>《网络是怎样连接的》</li>
</ul>
<p><strong>Linux 内核</strong></p>
<ul>
<li>《深入Linux内核架构》</li>
<li>《Linux 内核设计的艺术》</li>
<li>《Linux 内核完全剖析》 讲的是早期的内核代码</li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>分布式系统学习之路</title>
      <link>https://blueberry-universe.cn/ds/</link>
      <guid>https://blueberry-universe.cn/ds/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">分布式系统学习之路</source>
      <description>分布式系统学习之路</description>
      <content:encoded><![CDATA[
<ul>
<li><a href="/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2024-05-23-00/content.html" target="_blank">图解分布式共识算法 Raft（领导者选举）</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>一起刷力扣</title>
      <link>https://blueberry-universe.cn/lc/</link>
      <guid>https://blueberry-universe.cn/lc/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">一起刷力扣</source>
      <description>一起刷力扣
基础



1、数组
入门






三路快排





对撞指针






滑动窗口






更多练习




2、查找表
set &amp;amp;&amp;amp; map 入门




set &amp;amp;&amp;amp; map 练习







查找表问题






键值选择






滑动窗口 + 查找表




二分搜索树的顺序性

...</description>
      <content:encoded><![CDATA[
<h2>基础</h2>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-08-23-00/content.html" target="_blank">如何写出正确的代码 ✅</a></li>
</ul>
<h2>1、数组</h2>
<h3>入门</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-16-00/content.html" target="_blank">0283  移动零 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-17-00/content.html" target="_blank">0027  移动元素 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-18-00/content.html" target="_blank">0026  删除有序数组中的重复项 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-19-00/content.html" target="_blank">0080  删除有序数组中的重复项 II ✅</a></li>
</ul>
<h3>三路快排</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-20-00/content.html" target="_blank">0075  颜色分类 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-22-00/content.html" target="_blank">0088  合并两个有序数组 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-23-00/content.html" target="_blank">0215  数组中的第K个最大元素 ✅</a></li>
</ul>
<h3>对撞指针</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-24-00/content.html" target="_blank">0167  两数之和 II - 输入有序数组 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-25-00/content.html" target="_blank">0125   验证回文串 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-26-00/content.html" target="_blank">0345  反转字符串中的元音字母 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-27-00/content.html" target="_blank">0011  盛最多水的容器 ✅</a></li>
</ul>
<h3>滑动窗口</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-31-00/content.html" target="_blank">0209  长度最小的子数组 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-05-00/content.html" target="_blank">0003  无重复字符的最长子串 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-06-00/content.html" target="_blank">0438  找到字符串中所有字母异位词 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-06-01/content.html" target="_blank">0076   最小覆盖子串 ✅</a></li>
</ul>
<h3>更多练习</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-31-01/content.html" target="_blank">0169   多数元素 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2024-12-31-02/content.html" target="_blank">0189   轮转数组 ✅</a></li>
</ul>
<h2>2、查找表</h2>
<h3>set &amp;&amp; map 入门</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-07-00/content.html" target="_blank">0349  两个数组的交集 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-09-00/content.html" target="_blank">0350  两个数组的交集 II ✅</a></li>
</ul>
<h3>set &amp;&amp; map 练习</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-10-00/content.html" target="_blank">0242  有效的字母异位词 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-13-00/content.html" target="_blank">0202  快乐数 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-14-00/content.html" target="_blank">0290  单词规律 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-15-00/content.html" target="_blank">0205  同构字符串 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-15-01/content.html" target="_blank">0451  根据字符出现频率排序 ✅</a></li>
</ul>
<h3>查找表问题</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-16-00/content.html" target="_blank">0001  两数之和 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-17-00/content.html" target="_blank">0015  三数之和 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-18-00/content.html" target="_blank">0018  四数之和 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-23-00/content.html" target="_blank">0016  最接近的三数之和 ✅</a></li>
</ul>
<h3>键值选择</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-00/content.html" target="_blank"> 0454. 四数相加 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-01/content.html" target="_blank">0049. 字母异位词分组 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-02/content.html" target="_blank">0447. 回旋镖的数量 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-03/content.html" target="_blank">0149. 直线上最多的点数 ✅</a></li>
</ul>
<h3>滑动窗口 + 查找表</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-04/content.html" target="_blank">0219  存在重复元素 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-05/content.html" target="_blank">0217  存在重复元素 ✅</a></li>
</ul>
<h3>二分搜索树的顺序性</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-24-06/content.html" target="_blank">0220  存在重复元素 III ✅</a></li>
</ul>
<h2>3、链表</h2>
<h3>入门</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-25-00/content.html" target="_blank">0206  反转链表 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-25-01/content.html" target="_blank">0092  反转链表 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-26-00/content.html" target="_blank">0083  删除排序链表中的重复元素 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-27-00/content.html" target="_blank">0086  分隔链表 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-27-01/content.html" target="_blank">0328  奇偶链表 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-27-02/content.html" target="_blank">0231  2 的幂 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-27-03/content.html" target="_blank">0445  两数相加 II ✅</a></li>
</ul>
<h3>虚拟头结点的使用</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-28-00/content.html" target="_blank">0203  移除链表元素I ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-29-00/content.html" target="_blank">0082  删除排序链表中的重复元素 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-29-01/content.html" target="_blank">0021  合并两个有序链表 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-01-29-02/content.html" target="_blank">0024. 两两交换链表中的节点 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-00/content.html" target="_blank">0025. K 个一组翻转链表 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-01/content.html" target="_blank">0147. 对链表进行插入排序 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-02/content.html" target="_blank">0148. 排序链表 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-03/content.html" target="_blank">0237  删除链表中的节点 II ✅</a></li>
</ul>
<h3>双指针</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-04/content.html" target="_blank">0019  删除链表的倒数第 N 个结点 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-05/content.html" target="_blank">0143  重排链表 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-06/content.html" target="_blank">0234  回文链表 II ✅</a></li>
</ul>
<h2>4、栈，队列，优先队列</h2>
<h3>栈</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-02-02-07/content.html" target="_blank">0020  有效的括号 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-03-06-00/content.html" target="_blank">0150  逆波兰表达式求值 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-03-06-01/content.html" target="_blank">0071  简化路径 ✅</a></li>
<li><a href>0341  扁平化嵌套列表迭代器</a></li>
</ul>
<h3>队列</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-03-07-00/content.html" target="_blank">0102  二叉树的层序遍历 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-05-22-00/content.html" target="_blank">0107  二叉树的层序遍历 II ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-05-22-01/content.html" target="_blank">0103  二叉树的锯齿形层序遍历 ✅</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-05-22-02/content.html" target="_blank">0199  二叉树的右视图 ✅</a></li>
</ul>
<h3>广度优先搜索</h3>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2025-05-27-00/content.html" target="_blank">0279  完全平方数 ✅⭐️</a></li>
<li><a href>0127  单词接龙</a></li>
<li><a href>0126  单词接龙 II</a></li>
</ul>
<h3>优先队列</h3>
<ul>
<li><a href>0347  前 K 个高频元素</a></li>
<li><a href>0023  合并 K 个升序链表</a></li>
</ul>
<h2>5、二叉树</h2>
<h3>基础</h3>
<ul>
<li><a href>0111  二叉树的最小深度</a></li>
<li><a href>0226  翻转二叉树</a></li>
<li><a href>0100  相同的树</a></li>
<li><a href>0101  对称二叉树</a></li>
<li><a href>0222  完全二叉树的节点个数</a></li>
<li><a href>0110  平衡二叉树</a></li>
</ul>
<h3>递归终止条件</h3>
<ul>
<li><a href>0112  路径总和</a></li>
<li><a href>0111  二叉树的最小深度</a></li>
<li><a href>0404  左叶子之和</a></li>
</ul>
<h3>递归问题的定义</h3>
<ul>
<li><a href>0257  二叉树的所有路径</a></li>
<li><a href>0113  路径总和 II</a></li>
<li><a href>0129  求根节点到叶节点数字之和</a></li>
<li><a href>0437  路径总和 III</a></li>
</ul>
<h3>二分搜索树</h3>
<ul>
<li><a href>0235  二叉搜索树的最近公共祖先</a></li>
<li><a href>0098  验证二叉搜索树</a></li>
<li><a href>0450  删除二叉搜索树中的节点</a></li>
<li><a href>0108  将有序数组转换为二叉搜索树</a></li>
<li><a href>0230  二叉搜索树中第 K 小的元素</a></li>
<li><a href>0236  二叉树的最近公共祖先</a></li>
</ul>
<h2>6、递归和回溯</h2>
<h3>基础</h3>
<ul>
<li><a href>0017  电话号码的字母组合</a></li>
<li><a href>0093  复原 IP 地址</a></li>
<li><a href>0131  分割回文串</a></li>
</ul>
<h3>排列</h3>
<ul>
<li><a href>0046  全排列</a></li>
<li><a href>0047  全排列 II</a></li>
</ul>
<h3>组合</h3>
<ul>
<li><a href>0077  组合</a></li>
<li><a href>0040  组合总和 II</a></li>
<li><a href>0216  组合总和 III</a></li>
<li><a href>0078  子集</a></li>
<li><a href>0090  子集 II</a></li>
<li><a href>0401  二进制手表</a></li>
</ul>
<h3>二维平面的回溯</h3>
<ul>
<li><a href>0079  单词搜索</a></li>
</ul>
<h3>floodfill</h3>
<ul>
<li><a href>0200  岛屿数量</a></li>
<li><a href>0130  被围绕的区域</a></li>
<li><a href>0417  太平洋大西洋水流问题</a></li>
</ul>
<h3>练习</h3>
<ul>
<li><a href>0051  N 皇后</a></li>
<li><a href>0052  N 皇后 II</a></li>
<li><a href>0037  解数独</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2022-04-05-00/002-N-Queens.html" target="_blank">0002  N-Queens</a></li>
</ul>
<h2>7、动态规划</h2>
<h3>基础</h3>
<ul>
<li><a href>0070  爬楼梯</a></li>
<li><a href>0120  三角形最小路径和</a></li>
<li><a href>0064  最小路径和</a></li>
</ul>
<h3>重叠子问题</h3>
<ul>
<li><a href>0343  整数拆分</a></li>
<li><a href>0279  完全平方数</a></li>
<li><a href>0091  解码方法</a></li>
<li><a href>0062  不同路径</a></li>
<li><a href>0063  不同路径 II</a></li>
</ul>
<h3>状态定义和状态转移</h3>
<ul>
<li><a href>0198  打家劫舍</a></li>
<li><a href>0213  打家劫舍 II</a></li>
<li><a href>0337  打家劫舍 III</a></li>
<li><a href>0309  买卖股票的最佳时机含冷冻期</a></li>
</ul>
<h3>背包问题</h3>
<ul>
<li><a href="https://mp.weixin.qq.com/s?__biz=MjM5ODYyMzAxNw==&amp;mid=2247483985&amp;idx=2&amp;sn=8d22c0a54cb5c3a7fb7aab6aa924d1f7&amp;chksm=a6c6a01791b1290111d2e91538c08a93dcbda71422fb2e733d40538e018e2f21cf335c415fbd&amp;scene=178&amp;cur_album_id=1504450321060855809#rd" target="_blank" rel="noopener noreferrer">0-1 背包基础</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2022-09-26-00/content.html" target="_blank">0416  分割等和子集 (1)</a></li>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2022-09-27-00/content.html" target="_blank">0416  分割等和子集 (2)</a></li>
<li><a href>0322  零钱兑换</a></li>
<li><a href>0377  组合总和 Ⅳ</a></li>
<li><a href>0474  一和零</a></li>
<li><a href>0139  单词拆分</a></li>
<li><a href>0494  目标和</a></li>
</ul>
<h3>最长上升子序列 LIS（Longest Increasing Subsequence）</h3>
<ul>
<li><a href>0300  最长递增子序列</a></li>
<li><a href>0376  摆动序列</a></li>
</ul>
<h3>最长公共子序列 LCS （Lonogest Common Sequence）</h3>
<ul>
<li><a href>1143  最长公共子序列</a></li>
</ul>
<h2>8、贪心算法</h2>
<ul>
<li><a href>0455  分发饼干</a></li>
<li><a href>0392  判断子序列</a></li>
<li><a href>0435  无重叠区间</a></li>
<li><a href>0279  完全平方数</a></li>
</ul>
<h2>待分类</h2>
<ul>
<li><a href="/%E5%8A%9B%E6%89%A3%E5%88%B7%E9%A2%98/2022-04-09-00/0752-Open-The-Lock.html" target="_blank">0752  Open-The-Lock</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>操作系统学习之路</title>
      <link>https://blueberry-universe.cn/os/</link>
      <guid>https://blueberry-universe.cn/os/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">操作系统学习之路</source>
      <description>操作系统学习之路</description>
      <content:encoded><![CDATA[
<ul>
<li><a href="/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/2024-05-08-00/content.html" target="_blank">编译 Linux 内核 &amp;&amp; 添加系统调用</a></li>
<li><a href="/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/2024-11-13-00/content.html" target="_blank">裸机程序也能调试?</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>优雅的编程语言 Python</title>
      <link>https://blueberry-universe.cn/languages/</link>
      <guid>https://blueberry-universe.cn/languages/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">优雅的编程语言 Python</source>
      <description>优雅的编程语言 Python</description>
      <content:encoded><![CDATA[
<ul>
<li><a href="/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/2022-10-15-00/content.html" target="_blank">Python 天生支持多态</a></li>
<li><a href="/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/2022-12-06-00/content.html" target="_blank">Python 函数天生带有暂停键</a></li>
<li><a href="/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/2023-02-08-00/content.html" target="_blank">彻底理解 Python 装饰器</a></li>
<li><a href="/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/2023-02-15-00/content.html" target="_blank">彻底理解 Python 万物皆对象</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>蓝莓的胡思乱想</title>
      <link>https://blueberry-universe.cn/idea/</link>
      <guid>https://blueberry-universe.cn/idea/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">蓝莓的胡思乱想</source>
      <description>蓝莓的胡思乱想</description>
      <content:encoded><![CDATA[
<ul>
<li><a href="/%E8%93%9D%E8%8E%93%E9%9A%8F%E4%BE%BF%E6%89%AF/2022-04-29-00/%E6%80%9D%E8%80%83%E7%9A%84%E7%BB%B4%E5%BA%A6%E5%92%8C%E4%BB%98%E8%B4%B9%E6%84%8F%E8%AF%86.html" target="_blank">思考的维度和付费意识</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>计算机网络学习之路</title>
      <link>https://blueberry-universe.cn/cn/</link>
      <guid>https://blueberry-universe.cn/cn/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">计算机网络学习之路</source>
      <description>计算机网络学习之路</description>
      <content:encoded><![CDATA[
<ul>
<li><a href="/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/2024-05-07-00/content.html" target="_blank">彻底搞懂虚拟网络搭建</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>图解分布式共识算法 Raft（领导者选举）</title>
      <link>https://blueberry-universe.cn/2024-05-23-00/</link>
      <guid>https://blueberry-universe.cn/2024-05-23-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">图解分布式共识算法 Raft（领导者选举）</source>
      <description>图解分布式共识算法 Raft（领导者选举）
你好啊，我是蓝莓，在这篇文章中我们来聊聊 Raft ~
为什么要使用分布式技术呢？
在互联网上每天产生的数据量是非常大的，甚至我们在使用软件的过程中，每一次按钮的点击和屏幕的滑动都会被记录下来形成日志。对于这些大量的数据进行存储是一个问题，进行分析也是一个问题。因此分布式技术的出现就是因为：当一台机器干不动的...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，在这篇文章中我们来聊聊 Raft ~</p>
<p>为什么要使用分布式技术呢？</p>
<p>在互联网上每天产生的数据量是非常大的，甚至我们在使用软件的过程中，每一次按钮的点击和屏幕的滑动都会被记录下来形成日志。对于这些大量的数据进行存储是一个问题，进行分析也是一个问题。因此分布式技术的出现就是因为：当一台机器干不动的时候，联合众多机器一起干，分布式也不是凭空产生的，都是随着实际问题的产生而产生的。因此如何让众多的机器能够协调成为一个整体就成为了一个重要的问题。</p>
<p><strong>Raft 算法论文</strong></p>
<p>原文传送门：https://ramcloud.atlassian.net/wiki/download/attachments/6586375/raft.pdf</p>
<p>中文翻译版：https://github.com/maemual/raft-zh_cn</p>
<p><strong>目标：</strong></p>
<ol>
<li>Raft：关于 Raft 的基本认识</li>
<li>Leader Election：领导者选举的具体过程</li>
<li>RPC：使用到的两种 RPC 的论文原图</li>
</ol>
<h2>1 Raft</h2>
<p>既然我们知道了，Raft 所要解决的问题就是协调一组机器作为一个整体进行工作。那么 Raft 是要做什么呢？回想一下现实生活中的例子，一个部门的人一起来完成同一件事情，那么这个部门肯定是有一个 <code>老大</code> 的，这个老大做的事情就是对下面的人发号施令，老大让他们干什么，他们就干什么。如果有一天这个老大突然生病了，估计要请上那么一两个月的假来养病，这时候这个部门没有 <code>老大</code> 了，那可怎么办，比较简单的方法当然是从这个部门里面选择一个人作为新的老大咯继续对下面的人发号施令了呀。</p>
<p>Raft 共识算法将达成共识这件事情拆分成为了三个部分：</p>
<ol>
<li>Leader Election 领导者选举（主要来讲如何选老大）</li>
<li>Log Replication 日志复制（如何发号施令）</li>
<li>Safety 安全性（为保证算法能够正确运行，对前两者的补充）</li>
</ol>
<p>在这篇文章中，我们只说领导者选举这个部分</p>
<h2>2 Leader Election</h2>
<p>在 Raft 中选举领导是基于投票的，我们就假设这个部门一共有三个人，我们来看看这三个人是如何根据一套规则选择出一个 <code>Leader</code> 并且维护领导者权威的。</p>
<h3>三种状态</h3>
<p></p>
<p>在 Raft 算法中，每个 Raft 节点都处于三种状态中的一个，分别为：</p>
<ol>
<li>Leader 领导者</li>
<li>Candidate 候选人</li>
<li>Follower 追随者</li>
</ol>
<h3>记录状态使用的字段</h3>
<p>在本篇文章中，我们只说领导者选举，所以我们只使用到了这几个字段来记录状态：</p>
<ol>
<li>currentTerm：Raft 节点当前所处的任期</li>
<li>votedFor：Raft 节点在 这一次任期中把票投给了谁</li>
</ol>
<p>在 Raft 论文中的原图如下所示：</p>
<p></p>
<p>每个 Raft 节点都有一个倒计时的时钟，你可以为这个倒计时的时钟指定一个倒计时的下限和上限，假设我们指定下限为 <code>300ms</code> 和上限为 <code>400ms</code> ，如果这组人中是有 <code>Leader</code> 的，比如我们约定好，如果谁当选了 <code>Leader</code> 就每隔 <code>150ms</code> 就发送一次心跳消息，这样可以通知其他的 Raft 节点这组机器里面是有 <code>Leader</code> 的，从而告诉他们不用毛遂自荐了。</p>
<p>其实发送心跳的消息只要能在每个节点的时钟超时之前收到就可以了，这样就不会发生一直有人要竞选的尴尬局面。之所以我们要让时钟处于 <code>300ms</code> 到 <code>400ms</code> 之间随机选一个数，这是因为，如果大家都是使用同一个时间进行倒计时，那么大家大概率在同一时间超时，大家同时发起选举，每个人都给自己投一票，这样下去可能永远不会有人收到半数以上的投票，因为一轮选举中（就是每个任期中）每个人都只能投一票出去，除非进入到下一轮选举才能够再次投票。随机化的倒计时方法可以很好的避免这种尴尬局面的产生，让大家不在同一时间超时就不会同时发起选举了。</p>
<p><strong>有领导吗</strong></p>
<p>在一组计算机刚刚启动的时候是没有 <code>Leader</code> 的，这时候每个节点都在等待时钟超时，如果自己的时钟一旦超时，就主动发起选举，我们可以发现，大雄的倒计时剩余的时间最短，所以一定是大雄率先发起选举。</p>
<p></p>
<p><strong>大雄到时间了</strong></p>
<p>这时候大雄已经超时了</p>
<p></p>
<p><strong>大雄发送要票请求</strong></p>
<p>大雄首先将自己推荐为候选人 Candidate，然后将自己的  <code>CurrentTerm</code> 在原来的基础上增加 1。这说明大雄发现，在上一个任期中一直没有 <code>Leader</code> 通知我领导人的存在，所以我要主动进入到下一轮的选举中进行选举。</p>
<p>大雄做的事情：</p>
<ol>
<li>将自己的任期 CurrentTerm 加 1</li>
<li>将自己的 Role 从 Follower 转换为 Candidate 并给自己投上一票</li>
<li>用小本本记录自己已经获得的选票数量，现在大雄的 <code>votes</code> 记录为 1，每当 <code>votes</code> 的值增加一次的时候，他就算一算自己的选票数量是不是超过了总数的一半，一旦超过一半，大雄就把自己从 Candidate 转变为 Leader 成为真正的领导人</li>
</ol>
<p>在实现中大雄通过 <code>RPC</code> 向其他人发送 <code>RequestVote</code> RPC 请求进行要票</p>
<p>被要票的人做的事情：</p>
<ol>
<li>首先看看要票人的任期是不是比自己小：如果要票人的任期比自己小，那就直接拒绝给他投票，并且告诉他自己的任期是什么，当要票人收到回复后一旦发现自己的任期已经落后了，要票人就会直接从 <code>Candidate</code> 变为 <code>Follower</code> 并且重置自己的时钟以及对齐任期</li>
<li>如果要票人的任期大于自己：那被要票的人就将自己的任期提升，保持最高的任期，说明被要票的人应该注意到，现在已经进入了更新的一轮的选举过程了，这时候被要票的人就拥有了在新一轮选举中的投票权，直接同意投票给要票人即可</li>
<li>如果要票人的任期等于自己：那这时候被要票的人就看看自己是不是已经投过票了，如果被要票的人还没有投过票那就直接同意投给要票人即可，如果被要票的人投过票了就直接拒绝即可</li>
</ol>
<p>关于第 3 点：如果被要票的人投过票了，还可以检查一下这个票是不是投给当前正在向自己要票的这个人，因为在网络环境中很有可能被要票人的 <code>RPC</code> 回复消息丢失的情况，所以要票人没有收到回复，不太确定是拒绝了自己还是同意了自己，所以这时候要票人可以再次发送一次要票请求进行尝试</p>
<p></p>
<p><strong>静香支持大雄</strong></p>
<p>我们可以发现，静香所处的条件是：要票人的任期大于自己，因此静香做如下的事情：</p>
<ol>
<li>静香的 CurrentTerm 和 大雄的 Term 对齐，更新为 1</li>
<li>静香投票给大雄，使用 VotedFor 从 -1 修改为 大雄，其中 -1 在本文中代表没有投票给任何人的意思</li>
<li>重置倒计时时钟：一旦同意投票给大雄，意味着静香认可了大雄，所以答应大雄在一段时间内不会再次发起选举，所以要将自己的时钟重置</li>
</ol>
<p>大雄做的事情：</p>
<p>每次大雄收到一票后都要检查一下自己的 <code>votes</code> 是不是超过总节点数的一半了，一旦超过一半就可以直接从 <code>Candidate</code> 变身为 <code>Leader</code> 了</p>
<ol>
<li>大雄需要检查投票是否成功，如果投票成功直接给自己的 <code>votes</code> 增加 1，然后看看是不是能够变成 <code>Leader</code></li>
<li>如果投票没有成功，那就要检查一下被要票人的任期，如果被要票人的任期小于等于自己，那么就说明被要票人已经投给别人票了，在这一次选举中不能给当前这个要票人进行投票了，如果被要票人的任期大于自己，那说明要票人的任期落后了，要票人应该从 <code>Candidate</code> 变为 <code>Follower</code> 并且重置自己的时钟，同时将自己的任期和这个更新的任期对齐</li>
</ol>
<p>显然在这里大雄所做的事情应该是属于第 1 种情况</p>
<p></p>
<p><strong>静香苦等，多啦a梦奋笔疾书</strong></p>
<p>当静香投票成功后，静香就开始等待心跳，所谓的心跳就是一个 <code>RPC</code> ，在论文中起的名字叫做 <code>AppendEntries</code></p>
<p><code>Leader</code> 需要通过这样的方式来告诉所有人，当前是有 <code>Leader</code> 的，每次你们收到我的心跳消息后，你们都要重置自己的时钟</p>
<p></p>
<p><strong>哆啦a梦支持大雄</strong></p>
<p>这时候大雄收到了 哆啦a梦的投票，不过已经没有什么用处了，大雄收到是没有问题的，我们需要在实现的过程中增加这一步的边界条件判断，如果已经是 <code>Leader</code> 了，收到后续的选票后要看看对方是同意了还是不同意，具体的事情和刚才收到静香的投票的时候是一样的：</p>
<ol>
<li>大雄需要检查投票是否成功，如果投票成功直接给自己的 <code>votes</code> 增加 1，然后看看是不是能够变成 <code>Leader</code>，如果自己已经是 <code>Leader</code> 了，那就不用再变咯</li>
<li>如果投票没有成功，那就要检查一下被要票人的任期，如果被要票人的任期小于等于自己，那么就说明被要票人已经投给别人票了，在这一次选举中不能给当前这个要票人进行投票了，如果被要票人的任期大于自己，那说明要票人的任期落后了，要票人应该从 <code>Leader</code> 变为 <code>Follower</code> 并且重置自己的时钟，同时将自己的任期和这个更新的任期对齐</li>
</ol>
<p></p>
<p><strong>来自大雄的心跳</strong></p>
<p>这时候，大雄要宣布自己的主动，那就是使用 <code>AppendEntries</code> RPC 向所有下属发送消息，证明领导人是存在的，告诉他们，你们不用发起选举了啊，都听我的号令</p>
<p></p>
<p><strong>响应 Leader 的心跳</strong></p>
<p>每次收到 <code>Leader</code> 的心跳后，他们 <code>Follower</code> 都要做这样的事情：</p>
<ol>
<li>如果自己的任期比当前的 <code>Leader</code> 小，那就对齐自己的任期，并且把 <code>VotedFor</code> 修改为 <code>-1</code> ，记住，<code>VotedFor</code> 只有在自己的任期增加的时候才可以修改为 <code>-1</code>，因为只有来到更新的一轮中，自己才能重新获得新的一次投票权</li>
<li>如果自己的任期和当前的 <code>Leader</code> 相等，那么自己直接回复 <code>Leader</code> 并说，我已经收到你的心跳了，而且重置了自己的时钟，这代表中 <code>Follower</code> 认可了 <code>Leader</code> 的权威，并且答应在一段时间内不会再次发起选举</li>
<li>如果自己的任期大于当前的 <code>Leader</code>，那也很简单，只需要回复当前的 <code>Leader</code> 说，我的任期都已经比你高了，你不能再继续当 <code>Leader</code> 了，你赶紧和我的任期对齐之后变成 <code>Follower</code> 吧</li>
</ol>
<p></p>
<p><strong>大雄不干了！产生宕机的罪魁祸首</strong></p>
<p>在现实世界中，每个节点都是有可能出现问题的，比如大雄去睡觉了，这时候大雄肯定不会在梦中继续向其他节点发送心跳消息了，过一会儿如果大家没有收到心跳，率先超时的那个节点就会率先发起新一轮的选举，你可以发现，分布式系统是允许某个节点出现问题的，即使它宕机了，也还是能继续运行下去</p>
<p>可见，下一次就是哆啦a梦率先发起选举了</p>
<p></p>
<p><strong>多啦a梦超时，开始竞选</strong></p>
<p>重复刚才的过程，哆啦a梦增加自己的任期等一系列工作，发送要票请求给其他人</p>
<p></p>
<p><strong>静香投票给哆啦</strong></p>
<p>虽然哆啦a梦并不会收到大雄的回复，由于这是一个3节点的集群，所以只要哆啦a梦能拿到2票，就可以成功当选 <code>Leader</code></p>
<p></p>
<p><strong>收到哆啦a梦的心跳</strong></p>
<p>这时候，哆啦a梦开始发送心跳维护自己的权威</p>
<p></p>
<p><strong>回复多啦a梦的心跳</strong></p>
<p>哆啦a梦收到静香的响应</p>
<p></p>
<h2>3 RPC</h2>
<p>我们在本文中提到了两个 RPC，对照一下这些 RPC 中出现的字段，我们就很好理解是如何完成图中所说的那些事情了</p>
<ol>
<li>RequestVote</li>
<li>AppendEntries</li>
</ol>
<h3>RequestVote</h3>
<p></p>
<h3>AppendEntries</h3>
<p></p>


]]></content:encoded>
    </item>
    <item>
      <title>002-N-Queens</title>
      <link>https://blueberry-universe.cn/2022-04-05-00/</link>
      <guid>https://blueberry-universe.cn/2022-04-05-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">002-N-Queens</source>
      <description>002-N-Queens
这篇文章讨论下 LeetCode 上边儿的 51 号问题： N 皇后 (N Queens)
1 问题描述：

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案...</description>
      <content:encoded><![CDATA[
<p>这篇文章讨论下 LeetCode 上边儿的 <strong>51</strong> 号问题： N 皇后 (N Queens)</p>
<h2>1 问题描述：</h2>
<blockquote>
<p>n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。</p>
<p>给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。</p>
<p>每一种解法包含一个不同的 n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。</p>
<p>任意两个皇后不能处于 同行、同列或者斜线直线上。</p>
</blockquote>
<p>此问题要求给出所有合法的皇后摆放方式。</p>
<p><strong>举个例子</strong></p>
<p></p>
<p>可见上图，任意两个皇后之间都不在同一行上，也不在同一列上，也不在斜线上。所谓斜线就是像五子棋那样的斜线，而在 N 皇后的摆放规则中是不允许这样的。</p>
<p>这个例子是当 n 等于 4 的时候，这是一个 4 行 4 列的棋盘，并且这时候你拥有 4 个棋子，这 4 个棋子的摆放方式要符合刚才的三个不。</p>
<p>当你的程序输入的值为 n 的时候希望你给所有的摆放方式的解。</p>
<h2>2 解题思路</h2>
<p>对于这样的问题，最直接的想法就是穷举所有的可能性。也就是说，你可以尝试所有的摆放方式，</p>
<p>当然，你可以按照一定的顺序把你手中的 n 个棋子全都摆好之后你再看一下当前的摆放方式是否符合要求。</p>
<p>另外，你也可以在按照一定的次序摆放的过程中顺便检查当前落下这颗棋子之后，此时的局面是不是就已经不符合 N 皇后的要求了呐？如果这时候就已经不符合要求了，那么你就可以尝试下一种摆放方式了，因为当前已经不符合，再继续摆下去也没有意义了。</p>
<p>那么在这里，我才用第二种方式，就是在摆放的过程中就边摆放边验证。</p>
<p><strong>举个例子</strong></p>
<p>这里我一行一行地来摆放棋子，并且每一行都从<strong>第 0 号</strong>格子开始依次尝试到<strong>第 n-1 号</strong>格子。因为要求不同行，所以每行至多一个棋子。</p>
<p>假设：</p>
<p>我们先摆放了第 0 号行的第 0 个位置一颗棋子，</p>
<p>接着摆放第 1 号行的第 0 个位置一颗棋子，</p>
<p>这时候我们就已经没有必要去尝试摆放第 2 号行了，因为此时已经不合法了。因为我们摆放的那两颗棋子位于了同一列上，那么这时候应该直接跳过第 1 号行的那种摆放方式而继续去尝试接下来的一种摆放方式。</p>
<p>那么这时候撤销第 1 号行摆放的棋子，然后尝试 1 号行且 1 号列的摆放方式，这时候你会发现，当前摆放位置的左上角的格子存在棋子，所以不合法。</p>
<p>再撤销刚才的棋子，这次尝试 1 号行且 2 号列的位置摆放棋子，现在你会发现，已经没有冲突了，那么这时候就可以在第 2 号行尝试所有的位置摆放棋子了，若冲突则换下一个位置尝试，直到所有的行都摆放上了棋子，这时候我们就得到了一个合法的摆放方式了！</p>
<p>相信你理解了~</p>
<p><strong>那么，如何验证合法性？</strong></p>
<p>每当我们摆放一颗棋子之后，我们就已经检查当前摆放的位置的左上角方向上所有的格子是否存在棋子，检查当前位置的右上角方向上的所有格子是否存在棋子，最后检查一下当前位置的正上方的所有格子是否存在棋子。</p>
<p>那么为什么不用检查左下角方向上的所有格子、右下角方向上的所有格子、正下方的位置上所有的格子呐？答案就是：因为我们是一行一行的摆放呀，所以下边的行都还没有摆放棋子呀，所有也就用不着检查了呀！那么又为什么不用检查当前行上是否存在其他的棋子呐？因为我们每次只在一行上摆放一个棋子呀！从一开始就避免了在行方向上出现不合法的情况了。</p>
<h2>3 代码实现 C++</h2>
<p><strong>LeetCode 给的代码</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;string&gt;&gt; solveNQueens(int n) {</span>
<span class="line">        </span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>LeetCode 希望我们返回一个 <code>vector&lt;vector&lt;string&gt;&gt;</code> 类型的数据，这个类型的数据中每一个 <code>vector&lt;string&gt;</code> 记录了一个棋盘的样子。</p>
<p><code>vector&lt;string&gt;</code> 相当于一个二位数组，</p>
<p><code>vector&lt;vector&lt;string&gt;&gt;</code> 相当于一个三位数组，</p>
<p>意会一下，相信你理解了 ~</p>
<p><strong>算法思想</strong></p>
<p>整个算法的实现其实就是一个穷举的过程，属于 <strong>回溯算法</strong>。</p>
<p><strong>穷举的逻辑</strong></p>
<p>你会发现，我在此添加了两个函数，分别是 <strong>backtrack</strong> 和 <strong>isValid</strong>；</p>
<p>另外还有一个变量 <strong>res</strong>；</p>
<p>其中 <strong>res</strong> 的类型和 <strong>solveNQueens</strong> 函数的返回值类型一样，也就是说，我们使用 <strong>res</strong> 来记录所有合法的棋盘的样子，每穷举到一个合法的棋盘的时候，我们就添加到 <strong>res</strong> 中去。</p>
<p><strong>backtrack 回溯</strong></p>
<p>我们先来关注 <strong>backtrack</strong> 函数的逻辑</p>
<p>其他地方的代码都不要看，只看 <strong>backtrack</strong> 函数的代码以及它的注释</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;string&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">    vector&lt;vector&lt;string&gt;&gt; solveNQueens(int n) {</span>
<span class="line"></span>
<span class="line">        vector&lt;string&gt; board(n, string(n, '.'));</span>
<span class="line">        backtrack(board, 0);</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    // 用于判断当我们在 row 号行 col 号列</span>
<span class="line">    // 摆放一个棋子的时候，检查当前摆放是否合法</span>
<span class="line">    bool isValid(vector&lt;string&gt;&amp; board, int row, int col){</span>
<span class="line"></span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    // backtrack 函数的定义</span>
<span class="line">    // 在棋盘 board 中对 row 号行进行棋子的摆放</span>
<span class="line">    void backtrack(vector&lt;string&gt;&amp; board, int row){</span>
<span class="line">        if(row &gt;= board.size()){</span>
<span class="line">            // 应注意到 board.size() 的大小刚好是等于 n 的</span>
<span class="line">            // n 是棋盘的长宽</span>
<span class="line">            // 若 row 等于 n 说明我们正在对第 n 号行摆放棋子</span>
<span class="line">            // 而我们的行号从 0 开始编号</span>
<span class="line">            // 那也就说明了我们已经摆放完成了 n 个棋子</span>
<span class="line">            // 能够递归到这一层，说明之前的选择都是合法的</span>
<span class="line">            // 则当前 board 纳入到 res 中</span>
<span class="line">            res.push_back(board);</span>
<span class="line">            return;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 对于每一层都可以进行这样的选择</span>
<span class="line">        for(int col = 0; col &lt; board.size(); ++col){</span>
<span class="line">            // 做出选择前，对该情况判断是否合法</span>
<span class="line">            // 若不合法则直接跳过</span>
<span class="line">            if(!isValid(board, row, col)) continue;</span>
<span class="line"></span>
<span class="line">            // 做出对当前行的选择</span>
<span class="line">            // 并放入到 board 中</span>
<span class="line">            board[row][col] = 'Q';</span>
<span class="line"></span>
<span class="line">            // 对下一行进行选择</span>
<span class="line">            backtrack(board, row+1);</span>
<span class="line"></span>
<span class="line">            // 撤销当前行的选择</span>
<span class="line">            // 进行下一轮的循环，重新对当前行选择</span>
<span class="line">            board[row][col] = '.';</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>好啦！在你认真意会了 <strong>backtrack</strong> 函数之后，相信你已经懂了它的逻辑。</p>
<p>关键问题是，现在 <strong>isValid</strong> 函数的逻辑还没有写，那么接下来我们重点关注一下 <strong>isValid</strong> 函数的逻辑。</p>
<p><strong>isValid</strong></p>
<p>我在这里为了节约篇幅，单独把 <strong>isValid</strong> 函数给拿出来；</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 用于判断当我们在 row 号行 col 号列</span>
<span class="line">// 摆放一个棋子的时候，检查当前摆放是否合法</span>
<span class="line">bool isValid(vector&lt;string&gt;&amp; board, int row, int col){</span>
<span class="line">        // 因为是自上而下一行一行摆放皇后</span>
<span class="line">        // 所以在当前行的下方不存在皇后</span>
<span class="line">        // 则只需要检查此行上方的方向即可</span>
<span class="line"></span>
<span class="line">        // 1 检查左上方所有格子;注意对数组下标是否越界进行检查</span>
<span class="line">        for(int i = row-1, j = col-1; i &gt;= 0 &amp;&amp; j &gt;= 0; --i, --j){</span>
<span class="line">            if(board[i][j] == 'Q')</span>
<span class="line">                return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 2 检查正上方所有格子;注意对数组下标是否越界进行检查</span>
<span class="line">        for(int i = row-1; i &gt;= 0 ; --i){</span>
<span class="line">            if(board[i][col] == 'Q')</span>
<span class="line">                return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 3 检查右上方所有格子;注意对数组下标是否越界进行检查</span>
<span class="line">        for(int i = row-1, j = col+1; i &gt;= 0 &amp;&amp; j &lt; board.size(); --i, ++j){</span>
<span class="line">            if(board[i][j] == 'Q')</span>
<span class="line">                return false;</span>
<span class="line">        }</span>
<span class="line">		</span>
<span class="line">    	// 若以上三种情况都合法，则返回 true </span>
<span class="line">        return true;</span>
<span class="line"></span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>solveNQueens</strong></p>
<p>最后重点关注下 <strong>solveNQueens</strong> 函数</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">vector&lt;vector&lt;string&gt;&gt; solveNQueens(int n) {</span>
<span class="line"></span>
<span class="line">    vector&lt;string&gt; board(n, string(n, '.'));</span>
<span class="line">    backtrack(board, 0);</span>
<span class="line"></span>
<span class="line">    return res;</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这个函数就是，首先初始化一下最一开始的棋盘，因为还没有摆放任何的棋子，所以此时的棋盘的每一个位置都应该初始化为符号 <strong>.</strong> 一个点。</p>
<p>接着，我们看 <strong>backtrack</strong> 函数的定义：</p>
<p>在棋盘 board 中对 row 号行进行棋子的摆放</p>
<p>因为我们的行号从 0 开始，所以我们调用 <strong>backtrack</strong> 函数的时候应该先从第 0 号行开始，接着后边的工作，它都会自动进行下去了。</p>
<p><strong>完整代码</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// n 行 n 列， 其中 . 代表空，Q 代表皇后</span>
<span class="line">// 任意两个皇后都不能同行、同列、同对角线 </span>
<span class="line">// -&gt; 共六个方向</span>
<span class="line">// 输出所有合法的解</span>
<span class="line">// 返回一个 vector&lt;vector&lt;string&gt;&gt; 类型的数据</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;string&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">    vector&lt;vector&lt;string&gt;&gt; solveNQueens(int n) {</span>
<span class="line"></span>
<span class="line">        vector&lt;string&gt; board(n, string(n, '.'));</span>
<span class="line">        backtrack(board, 0);</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    bool isValid(vector&lt;string&gt;&amp; board, int row, int col){</span>
<span class="line">        // 因为是自上而下一行一行摆放皇后</span>
<span class="line">        // 所以在当前行的下方不存在皇后</span>
<span class="line">        // 则只需要检查此行上方的方向即可</span>
<span class="line"></span>
<span class="line">        // 1 检查左上方</span>
<span class="line">        for(int i = row-1, j = col-1; i &gt;= 0 &amp;&amp; j &gt;= 0; --i, --j){</span>
<span class="line">            if(board[i][j] == 'Q')</span>
<span class="line">                return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 2 检查正上方</span>
<span class="line">        for(int i = row-1; i &gt;= 0 ; --i){</span>
<span class="line">            if(board[i][col] == 'Q')</span>
<span class="line">                return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 3 检查右上方</span>
<span class="line">        for(int i = row-1, j = col+1; i &gt;= 0 &amp;&amp; j &lt; board.size(); --i, ++j){</span>
<span class="line">            if(board[i][j] == 'Q')</span>
<span class="line">                return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return true;</span>
<span class="line"></span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    void backtrack(vector&lt;string&gt;&amp; board, int row){</span>
<span class="line">        if(row &gt;= board.size()){</span>
<span class="line">            // 能够递归到这一层，说明之前的选择都是合法的</span>
<span class="line">            // 则当前 board 纳入到 res 中</span>
<span class="line">            res.push_back(board);</span>
<span class="line">            return;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 对于每一层都可以进行这样的选择</span>
<span class="line">        for(int col = 0; col &lt; board.size(); ++col){</span>
<span class="line">            // 做出选择前，对该情况判断是否合法</span>
<span class="line">            // 若不合法则直接跳过</span>
<span class="line">            if(!isValid(board, row, col)) continue;</span>
<span class="line"></span>
<span class="line">            // 做出对当前行的选择</span>
<span class="line">            // 并放入到 board 中</span>
<span class="line">            board[row][col] = 'Q';</span>
<span class="line"></span>
<span class="line">            // 对下一行进行选择</span>
<span class="line">            backtrack(board, row+1);</span>
<span class="line"></span>
<span class="line">            // 撤销当前行的选择</span>
<span class="line">            // 进行下一轮的循环，重新对当前行选择</span>
<span class="line">            board[row][col] = '.';</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>003-Minimum-Depth-of-Binary-Tree</title>
      <link>https://blueberry-universe.cn/2022-04-07-00/</link>
      <guid>https://blueberry-universe.cn/2022-04-07-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">003-Minimum-Depth-of-Binary-Tree</source>
      <description>003-Minimum-Depth-of-Binary-Tree
这篇文章谈论下二分搜索树的 广度优先遍历 也叫 层次遍历 还有个英文名字叫 BFS (Breadth First Search) 就是 广度优先搜索。
在 LeetCode 上边儿有一个对应的问题是 111 号问题：二叉树的最小深度。
1 题目描述

给定一个二叉树，找出其最小深度。
最...</description>
      <content:encoded><![CDATA[
<p>这篇文章谈论下二分搜索树的 <strong>广度优先遍历</strong> 也叫 <strong>层次遍历</strong> 还有个英文名字叫 <strong>BFS</strong> (Breadth First Search) 就是 广度优先搜索。</p>
<p>在 LeetCode 上边儿有一个对应的问题是 <strong>111</strong> 号问题：二叉树的最小深度。</p>
<h2>1 题目描述</h2>
<blockquote>
<p>给定一个二叉树，找出其最小深度。</p>
<p>最小深度是从根节点到最近叶子节点的最短路径上的节点数量。</p>
<p>**说明：**叶子节点是指没有子节点的节点。</p>
<p>其实就是距离根节点最近的那个叶子节点所处的那一层的深度。</p>
</blockquote>
<p><strong>举个例子</strong></p>
<p></p>
<p><strong>最小深度的定义</strong></p>
<p>这是一颗二叉树，那么这棵树对应的最小高度是多少呢 ？</p>
<p>答案是 2，你可以发现在第二层 [9, 20] 这两个节点就已经出现了叶子节点，所以节点 9 所在层的深度就是这个二叉树的最小深度。</p>
<p><strong>什么是层次遍历</strong></p>
<p>顾名思义，对于树而言，层次遍历就是一层一层的按照<strong>自上而下</strong>且<strong>自左向右</strong>的顺序访问每一个节点，这也被成为树的<strong>广度优先遍历</strong>。</p>
<p>对于上图而言，它的层次遍历的结果就是如下的节点访问顺序</p>
<p>[3, 9, 20, 15, 7]</p>
<p><strong>解题思路：如何寻找最小深度</strong></p>
<p>对于 9 号节点来说，用层次遍历就可以找到这个节点了，只要我们在遍历的过程中一边遍历一遍判断当前节点是否是叶子节点。这样，当我们第一次判断成功，也就是说，第一次寻找到的叶子节点所在的那一层的深度就是最终的答案了。这时，整个算法也就结束了。</p>
<p><strong>如何判断是否是叶子节点</strong></p>
<p>判断一个节点是否是叶子节点就等价于判断此节点是否满足左孩子和有孩子同时为空。</p>
<h2>2 层次遍历代码实现思路</h2>
<p><strong>初始状态</strong></p>
<p>层次遍历的过程需要一个队列作为辅助的数据结构，在以下的图中，我使用一个箭头代表队列的对头方向，初始情况下队列是空的。</p>
<p></p>
<p><strong>如何访问节点</strong></p>
<p>访问到的第一个节点，当然是位于二叉树的第一层的节点，而第一层也仅有一个节点。</p>
<p>但我们并不是直接访问它，为了代码的统一性，我们每次访问一个节点的时候都要从队列的队头取出一个节点然后访问它，并且在访问这个队头节点后还要把它的左孩子和右孩子依次入队。</p>
<p><strong>1 访问第 1 层的节点</strong></p>
<p></p>
<p>先让根节点入队，其中我用绿色箭头指向队列的头节点。接着，如果我们直接访问队头节点并且让此节点出队的话，那么后边就不知道该访问谁了，那么你发现了嘛，下一层的节点刚好就是队头节点的左孩子和右孩子，此时，当我们访问队头节点的时候顺便让它的左孩子和右孩子入队即可。</p>
<p>就像这样子：</p>
<p>并且这时候也可以放心地把头节点从队列中删除掉，然后头节点就变成了节点 9。</p>
<p></p>
<p><strong>到这里思考一个问题</strong></p>
<p>如果有一个需求，你想一行一行地把这些节点输出你该怎么办呢？如果按照刚才的策略进行的话，你每次都从队头取一个节点出来，可是你并不知道当前你取的这个队头的节点到底是位于树中的第几层呀？</p>
<p>其实：当你在访问第一个节点之前，队列的长度就是你即将访问的那一层的节点的数量，那么这时候你就可以在访问这一层之前使用一个变量记下这一层的节点数量，当你访问过这么多的节点后让输出换行。并且这时候你访问完了一层的节点，而且每访问一个节点那么它的左孩子和右孩子也会入队，所以此时队列中放满了下一层的节点，也就是说，这时候的队列的长度又成为了下一层节点的数量。如此，我们就知道了如何一层一层的输出每一层的节点了。</p>
<p><strong>2 访问第 2 层的节点</strong></p>
<p>现在队头指针已经指向了节点 9，那么还是刚才的过程，访问节点 9 并且将节点 9 的非空的孩子入队，而现在你可以发现，它的左孩子和有孩子都为空，所以不用入队任何节点。</p>
<p>这时，把节点 9 从队列中去除，接着访问新的队头节点：</p>
<p></p>
<p>依然是按照刚才的套路，访问节点 <strong>20</strong> 再将节点 <strong>20</strong> 的左孩子和右孩子入队。</p>
<p><strong>3 访问第 3 层节点</strong></p>
<p>访问节点 15</p>
<p></p>
<p>访问节点 7</p>
<p></p>
<p><strong>结束</strong></p>
<p>当我们访问完成所有的节点后，你会发现队列也变成了空。所以，判断层次遍历是否完成的条件就是判断队列是为空。若队列为空则遍历结束。</p>
<p></p>
<h2>3 代码实现 C++</h2>
<p><strong>LeetCode 给出的代码</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 节点的定义</span>
<span class="line">struct TreeNode {</span>
<span class="line">      int val;</span>
<span class="line">      TreeNode *left;</span>
<span class="line">      TreeNode *right;</span>
<span class="line">      TreeNode() : val(0), left(nullptr), right(nullptr) {}</span>
<span class="line">      TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}</span>
<span class="line">      TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}</span>
<span class="line"> };</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">// Solution 在这里写算法的实现 </span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int minDepth(TreeNode* root) {</span>
<span class="line">        </span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>对于 LeetCode 上边的这道题而言，并不需要遍历整个二叉树，而仅仅是找到第一个叶子节点的时候算法就可以结束了。因为我们是一层一层遍历的，所以访问到的第一个叶子节点所在的层一定是距离根节点最近的那一层，也就是题目中所叙述的那一层的最小深度。</p>
<p><strong>完整代码</strong></p>
<p>下边的代码只有一个函数，你可以对照这刚才所示的图片以及注释来理解这段代码。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int minDepth(TreeNode* root) {</span>
<span class="line">        // 若根节点不存在则 depth 为 0 </span>
<span class="line">        // 直接返回 0 即可</span>
<span class="line">        if(root == nullptr) return 0;</span>
<span class="line">        </span>
<span class="line">        queue&lt;TreeNode*&gt; q;</span>
<span class="line">        </span>
<span class="line">        // 把根节点入队，让代码统一</span>
<span class="line">        q.push(root);</span>
<span class="line">        </span>
<span class="line">        // 题目希望我们给出最小深度的值，</span>
<span class="line">        // 所以需要一个变量记录最小深度的值是什么</span>
<span class="line">        // depth 存储的是当前正在遍历的</span>
<span class="line">        // 那一层的深度</span>
<span class="line">        // 因为首先遍历的是根节点</span>
<span class="line">        // 根节点为第 1 层</span>
<span class="line">        // 则 depth 应初始化为 1</span>
<span class="line">        int depth = 1;</span>
<span class="line">        </span>
<span class="line">        // 队列不为空则说明遍历没有结束</span>
<span class="line">        while(!q.empty()) {</span>
<span class="line">            // 在还没有开始遍历一层的时候</span>
<span class="line">            // 队列 q 中存储了即将遍历的那一层的节点</span>
<span class="line">            // 所以 q.size() 就是即将遍历的这一层的节点数量</span>
<span class="line">            // 记录当前层的节点个数 sz</span>
<span class="line">            int sz = q.size();</span>
<span class="line">            </span>
<span class="line">            </span>
<span class="line">            // 一次 for 循环的完整执行</span>
<span class="line">            // 就是完成了二叉树的一层的遍历</span>
<span class="line">            for(int i = 0; i &lt; sz; ++i){</span>
<span class="line">                TreeNode* cur = q.front();</span>
<span class="line">                q.pop();</span>
<span class="line"></span>
<span class="line">                // 目标是找到第一个层次遍历中</span>
<span class="line">                // 所遇到的那个叶子节点</span>
<span class="line">                // 此时直接返回 depth</span>
<span class="line">                if(cur-&gt;left == nullptr &amp;&amp; cur-&gt;right == nullptr)</span>
<span class="line">                    return depth;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">                // 添加 cur 的相邻节点到队列中</span>
<span class="line">                // 对于二叉树而言就是添加其不为空的孩子节点</span>
<span class="line">                if(cur-&gt;left != nullptr)</span>
<span class="line">                    q.push(cur-&gt;left);</span>
<span class="line">                if(cur-&gt;right != nullptr)</span>
<span class="line">                    q.push(cur-&gt;right);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 此时完成了整个的 for 循环</span>
<span class="line">            // 维护 depth 变量的定义</span>
<span class="line">            // 继续遍历下一层的节点</span>
<span class="line">            depth += 1;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 对于这个题目来说</span>
<span class="line">        // 它并不会执行</span>
<span class="line">        // 因为一定可以在 while 循环中找到叶子节点</span>
<span class="line">        // 但我不这么写， LeetCode 编译出错</span>
<span class="line">        // 说存在没有返回值的情况</span>
<span class="line">        // 尽管这个 return 语句没用</span>
<span class="line">        // 为什么要减去 1 呢？</span>
<span class="line">        // 因为每遍历完成一层后就会为 depth 加上 1</span>
<span class="line">        // 而加上 1 后正准备要去遍历新的一层，</span>
<span class="line">        // 但是已经遍历结束，所以新的一层并不存在则要减去 1</span>
<span class="line">        return depth-1;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0752-Open-The-Lock</title>
      <link>https://blueberry-universe.cn/2022-04-09-00/</link>
      <guid>https://blueberry-universe.cn/2022-04-09-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0752-Open-The-Lock</source>
      <description>0752-Open-The-Lock
这篇文章讨论一个关于 BFS 应用的题目，LeetCode 上边儿的 752 号问题：打开转盘锁（0752-Open-The-Lock）
1 题目描述

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字： &amp;apos;0&amp;apos;, &amp;apos;1&amp;apos;, &amp;apos;2&amp;apos;, &amp;apos;3&amp;apos;, &amp;apos;4&amp;apos;, &amp;apos;5&amp;apos;, &amp;apos;6&amp;apos;, &amp;apos;7&amp;apos;, &amp;apos;8&amp;apos;, &amp;apos;9&amp;apos; 。每...</description>
      <content:encoded><![CDATA[
<p>这篇文章讨论一个关于 <strong>BFS</strong> 应用的题目，LeetCode 上边儿的 <strong>752</strong> 号问题：<strong>打开转盘锁</strong>（0752-Open-The-Lock）</p>
<h2>1 题目描述</h2>
<blockquote>
<p>你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字： '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转：例如把 '9' 变为 '0'，'0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。</p>
<p>锁的初始数字为 '0000' ，一个代表四个拨轮的数字的字符串。</p>
<p>列表 deadends 包含了一组死亡数字，一旦拨轮的数字和列表里的任何一个元素相同，这个锁将会被永久锁定，无法再被旋转。</p>
<p>字符串 target 代表可以解锁的数字，你需要给出解锁需要的最小旋转次数，如果无论如何不能解锁，返回 -1 。</p>
<p><strong>示例</strong></p>
<p>输入：deadends = [&quot;0201&quot;,&quot;0101&quot;,&quot;0102&quot;,&quot;1212&quot;,&quot;2002&quot;], target = &quot;0202&quot;
输出：6
解释：
可能的移动序列为 &quot;0000&quot; -&gt; &quot;1000&quot; -&gt; &quot;1100&quot; -&gt; &quot;1200&quot; -&gt; &quot;1201&quot; -&gt; &quot;1202&quot; -&gt; &quot;0202&quot;。
注意 &quot;0000&quot; -&gt; &quot;0001&quot; -&gt; &quot;0002&quot; -&gt; &quot;0102&quot; -&gt; &quot;0202&quot; 这样的序列是不能解锁的，
因为当拨动到 &quot;0102&quot; 时这个锁就会被锁定。</p>
</blockquote>
<p>那么先来理解下题目的意思，程序的输入是两个内容，一个是 **deadends ** 另外一个是 **target **</p>
<p>那么拨轮锁是什么东西呢，你可以脑补一下你行李箱上的那个锁子，可以拨动那个轮子然后转换成不同的数字。我简单画了一张图，可以参考下：</p>
<p></p>
<p>画图水平有限，只能画成这个样子了，绿色表示的是第几号波轮，再看绿色的圈圈中的数值就是指当前转到的密码是什么。如上图就是 <strong>0000</strong></p>
<p>现在向上拨动 <strong>0</strong> 号波轮，那么这时候对应的密码就从 <strong>0000</strong> 变成了 <strong>1000</strong></p>
<p><strong>deadends 是什么意思？</strong></p>
<p>在 **deadends ** 中存放了一组密码，指的就是在你拨动拨轮的过程中不能够在拨动的过程中拨出任意一个 **deadends ** 中存在的密码。</p>
<p>当前的 <strong>target</strong> = &quot;0202&quot;, 按照正常情况来说，我们先把 0 号拨轮拨成 0，然后把 1 号拨轮拨成 2 再 把 2 号拨轮拨成 0，最后 3 号拨轮拨成 2。我们也就打开密码锁了，但是在 <strong>deadends</strong> 中有一项是 <strong>0201</strong>，如果前三个已经拨成了 <strong>020</strong> 而在你拨动最后一个轮子的时候如果你向上拨动，你会先触发 <strong>0201</strong> 然后再触发 <strong>0202</strong>。那么相信你也理解了 <strong>deadends</strong> 的作用了，最后，题目要求我们寻找的是最少的拨动次数，只要单个拨轮的数字产生一次变化就视为拨动了一次。</p>
<p>题目的拨轮的初始状态为 <strong>0000</strong></p>
<h2>2 解题思路</h2>
<p>从题目，可以知道，要求：求得的值是一个最少的拨动次数。那么，广度优先搜索求解的就是最少的次数，我们可以从状态 <strong>0000</strong> 出发，然后遍历所有的密码状态，当然，我们要按照一定的顺序来遍历所有的密码，这个顺序就是按照广度优先的顺序遍历。其实，所有的密码状态可以被我们抽象称为数据结构中的 <strong>图结构</strong>。</p>
<p>为了简单，这里我直接说重要的地方，如果不太好理解，那么可以参考下边的这篇文章，先把这篇文章搞懂后，相信接下来的内容会更加好理解。</p>
<blockquote>
<p><strong>传送门</strong></p>
<p><a href="https://mp.weixin.qq.com/s/W80drJvvcheJ2nTc3vx3pg" target="_blank" rel="noopener noreferrer">BFS-求解二叉树的最小深度</a></p>
</blockquote>
<p><strong>到底是什么意思？举个例子</strong></p>
<p>拨动次序，从第 0 号拨轮开始依次拨动到第 3 号拨轮，每个拨轮的拨动方向有上下两种选择。那么也就意味着每一个密码状态节点共有 8 个相邻节点，因为我们可以从一个密码状态通过 8 种不同的操作得到另外一个密码状态。如果你学习过图结构，是不是忽然就能够理解了呢？</p>
<p>按照广度优先的策略，每次我们从队列中取一个节点出来访问它，并且把它的相邻节点插入到队尾。然后接着循环刚才的过程就好了。</p>
<p><strong>注意一个问题</strong></p>
<p>假如当前我们访问到的密码节点是 <strong>0001</strong>，这时候我们选择把 3 号拨轮，向上拨动那么节点 <strong>0002</strong> 就会插入到队列，我们迟早也会访问到节点 <strong>0002</strong>。</p>
<p>那么思考一下，如果我们现在访问到的节点是 <strong>0003</strong> ，这时候把第 3 号拨轮向下拨动就变成了 <strong>0002</strong> 节点，这时候 <strong>0002</strong> 节点也会插入到队尾。</p>
<p>这就产生了一个问题，我们会形成一个死循环，因为被访问过的状态再今后还会访问，这样会一直持续下去。有没有什么好方法，来解决这个问题呢？那就是，可以对每一个访问过的状态标记一下，当我们要把一个密码状态插入到队尾之前就先判断一下当前这个状态是不是已经被放进过队列中了，如果已经放进过了，那么我们直接跳过当前状态即可。在后边的程序中，我会使用一个布尔类型的数组来完成这件事情，当然你也可以选择使用哈希表或者字典等等都可以。但是使用数组的画，或许会更加高效，因为数组对于元素是随机访问的而若使用其他的数据结构还需要先查找再访问。</p>
<p>我简单化了一张图，可以参过来理解：</p>
<p>其实整个求解过程就是图的广度优先遍历，每个节点都会有 8 个相邻的节点，我只画出了很小的一部分，</p>
<p></p>
<p>顺便再来理解一下题目中的 <strong>deadends</strong></p>
<p>假设在 <strong>deadends</strong> 中有一个密码状态是 <strong>0008</strong>，而且现在的 target = <strong>0007</strong>。</p>
<p>其实它想表达的意思就是我们不能够通过节点 <strong>0008</strong> 来访问节点 <strong>0007</strong></p>
<p></p>
<p><strong>初始化注意的问题</strong></p>
<p>那么我们又如何来判断是否能够通过一个节点访问到另外一个节点呢，在刚才我们提到了一个布尔类型的数组，只要我们在程序开始运行之前，我们就在布尔类型的数组中标记这个节点是不能够加入队列的，那么我们的程序自然也就不会访问到 <strong>0008</strong> 这个节点了。</p>
<h2>3 代码实现 C++</h2>
<p><strong>LeetCode 给出的代码</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int openLock(vector&lt;string&gt;&amp; deadends, string target) {</span>
<span class="line"></span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在文章最下边我给出了完整的代码，你可以对照文章末尾的完整代码和这里的部分片段来结合起来理解，而在这里我会拆解每一个部分详细阐述：</p>
<p><strong>布尔类型的数组</strong></p>
<p>因为共有 4 个拨轮，每个拨轮又有 10 种状态（0~9），所以用这样的一个数组刚好可以记录某一个密码状态是否被访问过。</p>
<p>比如 visited[1][2][3][4] 就是表示说，密码状态 <strong>1234</strong> 时已经被加入到过队列了吗？当我们要加入 <strong>1234</strong> 这个状态到队列之前，我们先判断这个条件是否是 <strong>false</strong>。</p>
<p>visited[1][2][3][4] == true 表明已经已经被加入过了</p>
<p>visited[1][2][3][4] == false 表明没有被加入过</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 用于标记某个节点是否被访问过</span>
<span class="line">bool visited[10][10][10][10];</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>isVisited 函数</strong></p>
<p>为了方便，我把对一个密码状态是否被访问过的这个操作封装成了一个函数。</p>
<p>在程序中使用字符串对象来存储一个密码状态，由于数组下标需要整型，所以要先把每个字符转换成对应的整型最后直接返回这个结果就好了。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    bool isVisted(string s) {</span>
<span class="line">        unsigned int s0 = s[0] - '0';</span>
<span class="line">        unsigned int s1 = s[1] - '0';</span>
<span class="line">        unsigned int s2 = s[2] - '0';</span>
<span class="line">        unsigned int s3 = s[3] - '0';</span>
<span class="line">        </span>
<span class="line">        return visited[s0][s1][s2][s3];</span>
<span class="line">    }</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>visite 函数</strong></p>
<p>每当我们把一个密码状态放入队列后，放了防止下次重复放入相同的密码状态，所以需要在 <strong>visited</strong> 数组种标记一下，那么，我把这个标记的功能封装在了 <strong>visite</strong> 函数中，非常简单。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    void visite(string s) {</span>
<span class="line">        unsigned int s0 = s[0] - '0';</span>
<span class="line">        unsigned int s1 = s[1] - '0';</span>
<span class="line">        unsigned int s2 = s[2] - '0';</span>
<span class="line">        unsigned int s3 = s[3] - '0';</span>
<span class="line"></span>
<span class="line">        // cout &lt;&lt; &quot;visite : &quot; &lt;&lt; s &lt;&lt; endl;</span>
<span class="line"></span>
<span class="line">        visited[s0][s1][s2][s3] = true;</span>
<span class="line">    }</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>plusOne 函数</strong></p>
<p>当我们对密码状态 s 的第 j 号拨轮向上拨动一次那么就会产生一个新的密码状态，我把这个功能放在了 <strong>plusOne</strong> 函数中，这个函数会以字符串的形式返回拨动后的新的密码状态的字符串格式。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    // s[j] 向上拨动一次</span>
<span class="line">    string plusOne(string s, int j) {</span>
<span class="line">        if(s[j] == '9')</span>
<span class="line">            s[j] = '0';</span>
<span class="line">        else</span>
<span class="line">            s[j] += 1;</span>
<span class="line"></span>
<span class="line">        return s;</span>
<span class="line">    }</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>minusOne 函数</strong></p>
<p>当我们对密码状态 s 的第 j 号拨轮向下拨动一次那么就会产生一个新的密码状态，我把这个功能放在了 <strong>minusOne</strong> 函数中，这个函数会以字符串的形式返回拨动后的新的密码状态的字符串格式。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    // s[j] 向下拨动一次</span>
<span class="line">    string minusOne(string s, int j) {</span>
<span class="line">        if(s[j] == '0')</span>
<span class="line">            s[j] = '9';</span>
<span class="line">        else</span>
<span class="line">            s[j] -= 1;</span>
<span class="line"></span>
<span class="line">        return s;</span>
<span class="line">    }</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后就只剩下 <strong>openLock</strong> 的核心逻辑了，那么可以直接在完整代码中结合其他的部分和代码中的注释来理解最后的逻辑。</p>
<p><strong>完整代码</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">#include &lt;iostream&gt;</span>
<span class="line">#include &lt;vector&gt;</span>
<span class="line">#include &lt;queue&gt;</span>
<span class="line">#include &lt;cstring&gt;</span>
<span class="line">using namespace std;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line"></span>
<span class="line">    // 用于标记某个节点是否被访问过</span>
<span class="line">    bool visited[10][10][10][10];</span>
<span class="line"></span>
<span class="line">    void visite(string s) {</span>
<span class="line">        unsigned int s0 = s[0] - '0';</span>
<span class="line">        unsigned int s1 = s[1] - '0';</span>
<span class="line">        unsigned int s2 = s[2] - '0';</span>
<span class="line">        unsigned int s3 = s[3] - '0';</span>
<span class="line"></span>
<span class="line">        visited[s0][s1][s2][s3] = true;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    bool isVisted(string s) {</span>
<span class="line">        unsigned int s0 = s[0] - '0';</span>
<span class="line">        unsigned int s1 = s[1] - '0';</span>
<span class="line">        unsigned int s2 = s[2] - '0';</span>
<span class="line">        unsigned int s3 = s[3] - '0';</span>
<span class="line">        </span>
<span class="line">        return visited[s0][s1][s2][s3];</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    // s[j] 向上拨动一次</span>
<span class="line">    string plusOne(string s, int j) {</span>
<span class="line">        if(s[j] == '9')</span>
<span class="line">            s[j] = '0';</span>
<span class="line">        else</span>
<span class="line">            s[j] += 1;</span>
<span class="line"></span>
<span class="line">        return s;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    // s[j] 向下拨动一次</span>
<span class="line">    string minusOne(string s, int j) {</span>
<span class="line">        if(s[j] == '0')</span>
<span class="line">            s[j] = '9';</span>
<span class="line">        else</span>
<span class="line">            s[j] -= 1;</span>
<span class="line"></span>
<span class="line">        return s;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    int openLock(vector&lt;string&gt;&amp; deadends, string target) {</span>
<span class="line">        // 每个节点的相邻节点有 8 个</span>
<span class="line">    </span>
<span class="line">        // 初始化为每个节点都没有访问过</span>
<span class="line">        // 数组整个都初始化为 0 就代表了是 false</span>
<span class="line">        memset(visited, 0, sizeof(visited));</span>
<span class="line"></span>
<span class="line">        // 在 visited 中初始化不可达的顶点</span>
<span class="line">        // 遍历 deadends 中的每一个密码状态</span>
<span class="line">        // 把这些节点都标记为已经入队过</span>
<span class="line">        // 其实就是在说，这些结果不能够再被访问了</span>
<span class="line">        // 因为 BFS 每次都是从队列中取一个节点来访问</span>
<span class="line">        // 不能够入队就代表了不会从队列中被访问</span>
<span class="line">        for(auto s : deadends) {</span>
<span class="line">            visite(s);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 极端情况的考虑</span>
<span class="line">        // 如果 deadends 中存在 0000</span>
<span class="line">        // 又由于我们密码锁的初始状态就是 0000</span>
<span class="line">        // 所以我们无法从 0000 访问到任何节点</span>
<span class="line">        // 则程序返回 -1 表示无解</span>
<span class="line">        if(isVisted(string(&quot;0000&quot;)))</span>
<span class="line">            return -1;</span>
<span class="line">            </span>
<span class="line">        // step 记录的是</span>
<span class="line">        // 当前正在遍历的这些节点</span>
<span class="line">        // 从 0000 状态开始</span>
<span class="line">        // 最少需要拨动几次才能够触达</span>
<span class="line">        // 初始化为拨动 0 次</span>
<span class="line">        // 因为 0000 状态不需要拨动</span>
<span class="line">        // 0000 状态就是最初始的状态</span>
<span class="line">        int step = 0;</span>
<span class="line"></span>
<span class="line">        // 用 start 字符串记录初始状态 0000</span>
<span class="line">        string start = &quot;0000&quot;;</span>
<span class="line">        </span>
<span class="line">        // BFS 用到的辅助队列 q</span>
<span class="line">        queue&lt;string&gt; q;</span>
<span class="line"></span>
<span class="line">        // 让初始状态入队</span>
<span class="line">        q.push(start);</span>
<span class="line"></span>
<span class="line">        // 并且标记该状态已经入队过了</span>
<span class="line">        visite(start);</span>
<span class="line"></span>
<span class="line">        // 队列不为空则 BFS 未结束</span>
<span class="line">        while(!q.empty()) {</span>
<span class="line">            // 通过 size 可以知道当前遍历的那一层有多少个节点</span>
<span class="line">            // 每遍历完成 size 个节点后</span>
<span class="line">            // step 就应该增加 1 </span>
<span class="line">            int sz = q.size();</span>
<span class="line"></span>
<span class="line">            for(int i = 0 ; i &lt; sz ; ++i) {</span>
<span class="line">                // 从队头取一个节点出来</span>
<span class="line">                string cur = q.front();</span>
<span class="line">                // 并且删除队头节点</span>
<span class="line">                q.pop();</span>
<span class="line"></span>
<span class="line">                // 判断是否是目标 target</span>
<span class="line">                if(cur == target)</span>
<span class="line">                    return step;</span>
<span class="line"></span>
<span class="line">                // BFS 的套路</span>
<span class="line">                // 添加相邻节点</span>
<span class="line">                // 只不过这里的相邻节点需要自己来构建</span>
<span class="line">                // 共有 4 个拨轮</span>
<span class="line">                // 每个拨轮可以向上或向下两种拨动方式</span>
<span class="line">                for(int j = 0 ; j &lt; 4 ; ++j) {</span>
<span class="line">                    string plus_cur = plusOne(cur, j);</span>
<span class="line">                    // 入队之前要保证此节点没有被入队过</span>
<span class="line">                    if(!isVisted(plus_cur)) {</span>
<span class="line">                        q.push(plus_cur);</span>
<span class="line">                        // 入队后标记此节点已经入队过了</span>
<span class="line">                        visite(plus_cur);</span>
<span class="line">                    }</span>
<span class="line"></span>
<span class="line">                    string minus_cur = minusOne(cur, j);</span>
<span class="line">                    // 入队之前要保证此节点没有被入队过</span>
<span class="line">                    if(!isVisted(minus_cur)) {</span>
<span class="line">                        q.push(minus_cur);</span>
<span class="line">                        // 入队后标记此节点已经入队过了</span>
<span class="line">                        visite(minus_cur);</span>
<span class="line">                    }</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 维护 step 变量</span>
<span class="line">            step += 1;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 整个 BFS 结束后还没有找到解</span>
<span class="line">        // 则不可达</span>
<span class="line">        return -1;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line">int main() {</span>
<span class="line"></span>
<span class="line">    vector&lt;string&gt; deadends = {</span>
<span class="line">        &quot;0000&quot;</span>
<span class="line">    };</span>
<span class="line"></span>
<span class="line">    string target = &quot;8888&quot;;</span>
<span class="line">    </span>
<span class="line">    Solution solution;</span>
<span class="line">    int res = solution.openLock(deadends, target);</span>
<span class="line"></span>
<span class="line">    cout &lt;&lt; &quot;res : &quot; &lt;&lt; res &lt;&lt; endl;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">    return 0;</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0416 分割等和子集</title>
      <link>https://blueberry-universe.cn/2022-09-26-00/</link>
      <guid>https://blueberry-universe.cn/2022-09-26-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0416 分割等和子集</source>
      <description>0416 分割等和子集
哈喽 ~
你好啊，我是 蓝莓 ~
416 LeetCode

1 暴力搜索
理解题目是要把给定的 nums 数组中的元素拆分成集合 A 和 集合 B，使得 sum(A) 等于 sum(B)，也就是 sum(A) = sum(B) = sum(nums)/2  。
记 sum(nums) / 2 = C
最简单的方法就是遍历所有的...</description>
      <content:encoded><![CDATA[
<p>哈喽 ~</p>
<p>你好啊，我是 蓝莓 ~</p>
<h2>416 LeetCode</h2>
<p></p>
<h2>1 暴力搜索</h2>
<p>理解题目是要把给定的 <strong>nums</strong> 数组中的元素拆分成集合 <strong>A</strong> 和 集合 <strong>B</strong>，使得 <code>sum(A)</code> 等于 <code>sum(B)</code>，也就是 <code>sum(A) = sum(B) = sum(nums)/2 </code> 。</p>
<p>记 <code>sum(nums) / 2 = C</code></p>
<p>最简单的方法就是遍历所有的子集，从中挑出一个满足要求的集合，那么剩下的另外一半元素也一定就是满足要求的另外一个集合了。</p>
<h2>2 动态规划</h2>
<p>这个题目可以用 <strong>0-1 背包</strong> 的思路解决，因为本质就是从中寻找出一组数值，然后看看这些数值能不能刚好装满容量 <strong>C</strong> 。</p>
<p>那么 <strong>dp</strong> 数组要如何设置呢？</p>
<p><code>bool dp[nums.size()][C+1]</code></p>
<ol>
<li><code>nums.size()</code> 是数值的个数</li>
<li>取 <code>C+1</code> 是因为下标从 <code>0</code> 到 <code>C</code> 这么多种容量的情况</li>
</ol>
<p><code>dp[i][j]</code> 表示考虑 <code>[0...i]</code> 这些数值，且容量为 <code>j</code> 时，能否有一个数值的子集求和后刚好等于 <strong>C</strong>。</p>
<p>我们要求的 <strong>结果</strong> 就是 <code>dp[nums.size()-1][C]</code>，它代表了考虑所有的元素，并且容量为 <code>C</code> 的时候，能否从所有的元素中找到一个子集使得该集合的元素和等于 <code>C</code>。</p>
<ol>
<li>当 <code>dp[i][j] = true</code> 说明 考虑 <code>[0...i]</code> 这些编号的数值且容量为 <code>j</code> 的时候刚好可以装满容量 <code>j</code>，也就是说可以从 <code>[0...i]</code> 这些编号的数值中找到一个子集，使得该子集的数值和等于 <code>j</code>。</li>
<li>当 <code>dp[i][j] = true</code> 说明 考虑 <code>[0...i]</code> 这些编号的数值且容量为 <code>j</code> 的时候不能装满容量 <code>j</code>。</li>
</ol>
<p>那么<code>dp[i][j]</code> 的值取决于什么呢？</p>
<p>对于 <strong>第i号</strong> 数值可以选择 <strong>要</strong> 或 <strong>不要</strong></p>
<ol>
<li>选择 <strong>要</strong> 那么就要判断一下容量 <strong>j</strong> 能否装入 <strong>第i号</strong> 数值。如果可以装入，这时候还剩下的容量为 <code>j-nums[i]</code>，再考察一下 <code>dp[i-1][j-nums[i]]</code> 的情况，如果 <code>dp[i-1][j-nums[i]] = true</code> 则 <code>dp[i][j] = true</code> 。 <code>dp[i-1][j-nums[i]] = true</code> 表达的意思是：当我装进去 <strong>第i号</strong> 数值后，那么考虑上前边的那些数值，也就是编号为 <code>[0...i-1]</code> 的这些数值并且使用剩下来的 <code>j-nums[i]</code> 这么大的容量能否被前 <code>[0...i-1]</code> 这些编号的数值装满。如果不能的话，就是说，虽然把 <strong>第i号</strong> 数值装进去了，同时也消耗了 <code>nums[i]</code> 这么大的容量，但是剩下的空间并不能被 <code>[0...i-1]</code> 这些编号的数值的子集装满，这样同样不符合题目要求，所以 <code>dp[i][j]</code> 的值一方面取决于 <code>dp[i-1][j-nums[i]]</code> 的值。</li>
<li>如果选择 <strong>不要</strong> 那么 <code>dp[i][j] = dp[i-1][j]</code>，这个应该很好理解，如果你不要 <strong>第i号</strong> 数值，那么此时的结果其实和 <code>dp[i-1][j]</code> 是一样的。不要 <strong>第i号</strong> 数值的话，问题就变成了：考虑一下 <code>[0...i-1]</code> 这些编号的数值能否找到一个子集，并且这个子集的数值和能否刚好等于 <code>j</code>。</li>
</ol>
<p><strong>最终</strong></p>
<p><code>dp[i][j] </code></p>
<p><code>= dp[i-1][j-nums[i]] || dp[i-1][j]</code></p>
<p>只要，<strong>要</strong> 或 <strong>不要</strong> 两种决策方案种有一个方案是可以使得背包的容量被装满的，那么 <code>dp[i][j]</code> 就可以满足被装满的要求。</p>
<p><strong>总结一下</strong></p>
<ol>
<li>只要两种方案中有一个可以满足要求 <code>dp[i][j] = true</code></li>
<li>两种方案都不满足要求 <code>dp[i][j] =false</code></li>
</ol>
<p>你可以发现更新 <strong>第i号</strong> 行需要 <strong>第 i-1 号</strong> 行的数据作为支撑</p>
<p><strong>处理特殊行和列</strong></p>
<p>当背包的容量为 <code>0</code> 的时候，一定存在一个子集可以把背包装满，只要我们什么数值都不选就好了呀，这个子集就是 <strong>空集</strong> 呀。所以 <code>dp</code> 数组的第 <code>0</code> 列也就是容量为 <code>0</code> 的那一列的值都为 <code>true</code>。</p>
<p>因为更新 <strong>第i号</strong> 行的数据需要 <strong>第 i-1 号</strong> 行的数据作为支持，所以我们先专门计算出 <strong>第0号</strong> 行的值。在计算 0 列的时候，已经计算出了 <code>dp[0][0]</code> 的值，所以只需要计算 <code>dp[0][1...C]</code> 的值就可以了。这些值中只有那个容量刚好等于 <code>nums[0]</code> 的位置才能被刚好装满，其余的位置都是不能被装满的。</p>
<p>那么特殊行的处理代码就很简单了：</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 容量为 0 的时候都能装满 ==&gt; 可以都不装</span>
<span class="line">for(int i = 0 ; i &lt; nums.size() ; ++i)</span>
<span class="line">  dp[i][0] = true;</span>
<span class="line"></span>
<span class="line">// 当容量 &gt;= 1 的时候只有 dp[0][nums[0]] 能装满</span>
<span class="line">// 其他位置都装不满</span>
<span class="line">for(int j = 1 ; j &lt;= C ; ++j)</span>
<span class="line">  dp[0][j] = false;</span>
<span class="line"></span>
<span class="line">// dp[0][nums[0]] 能装满</span>
<span class="line">if(nums[0] &lt;= C) dp[0][nums[0]] = true;</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>dp 数组更新</strong></p>
<p>接下来，就是其他行的数值更新了。其他行的每个位置的值都可以根据上一行的结果推算出来</p>
<p>我们只需要更新 <code>dp[1...nums.size()-1][1...C]</code> 这些值即可，也就是排除了第 0 行 和 第 0 列。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">for(int i = 1 ; i &lt; nums.size() ; ++i) {</span>
<span class="line">  for(int j = 1 ; j &lt;= C ; ++j) {</span>
<span class="line">    // 容量不足以装入 i 号元素</span>
<span class="line">		// 那么只能选择不装 i 号元素了</span>
<span class="line">    if(nums[i] &gt; j)</span>
<span class="line">      dp[i][j] = dp[i-1][j];</span>
<span class="line">    else {</span>
<span class="line">      // 容量 j 能装入第 i 号元素</span>
<span class="line">      // 结果取 装入 i 号 或 不装入 i 号元素</span>
<span class="line">			// 只要其中一个方案成功即可</span>
<span class="line">      dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];</span>
<span class="line">    }</span>
<span class="line">  }</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>3 完整代码</h2>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool canPartition(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        int sum = 0;</span>
<span class="line">        for(int num : nums)</span>
<span class="line">            sum += num;</span>
<span class="line"></span>
<span class="line">        // sum 是奇数的时候是不可能分割的</span>
<span class="line">        if(sum % 2 != 0) return false;</span>
<span class="line"></span>
<span class="line">        // [0...nums.size()-1] 数值</span>
<span class="line">        // [0...C] 容量</span>
<span class="line">        int C = sum / 2;</span>
<span class="line">        // dp[i][j] 考虑 [0...i] 数值且容量为 j 时能否装满</span>
<span class="line">        bool dp[nums.size()][C+1];</span>
<span class="line"></span>
<span class="line">        // 容量为 0 的时候都能装满 ==&gt; 可以都不装</span>
<span class="line">        for(int i = 0 ; i &lt; nums.size() ; ++i)</span>
<span class="line">            dp[i][0] = true;</span>
<span class="line"></span>
<span class="line">        // 当容量 &gt;= 1 的时候只有 dp[0][nums[0]] 能装满</span>
<span class="line">        // 其他位置都装不满</span>
<span class="line">        for(int j = 1 ; j &lt;= C ; ++j)</span>
<span class="line">            dp[0][j] = false;</span>
<span class="line"></span>
<span class="line">        // dp[0][nums[0]] 能装满</span>
<span class="line">        if(nums[0] &lt;= C) dp[0][nums[0]] = true;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">        for(int i = 1 ; i &lt; nums.size() ; ++i) {</span>
<span class="line">            for(int j = 1 ; j &lt;= C ; ++j) {</span>
<span class="line">                // 容量不足以装入 i 号元素</span>
<span class="line">                // 先减去了第 i 号元素所需要的空间</span>
<span class="line">                // 然后才去装其他的元素的</span>
<span class="line">                if(nums[i] &gt; j)</span>
<span class="line">                    dp[i][j] = dp[i-1][j];</span>
<span class="line">                else {</span>
<span class="line">                    // 容量 j 能装入第 i 号元素</span>
<span class="line">                    // 结果取 装入 i 号 或 不装入 i 号元素</span>
<span class="line">                    // 两者中能够正好装满的那个结果</span>
<span class="line">                    // 不装入 i 号元素的时候是 j-0</span>
<span class="line">                    // 装入 i 号元素的时候是 j-nums[i]</span>
<span class="line">                    dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return dp[nums.size()-1][C];</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0416-状态压缩</title>
      <link>https://blueberry-universe.cn/2022-09-27-00/</link>
      <guid>https://blueberry-universe.cn/2022-09-27-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0416-状态压缩</source>
      <description>0416-状态压缩
哈喽 ~
你好啊 ~ 我是蓝莓 ~
LeetCode 416 （状态压缩）
在上一篇文章中，提到了怎么使用 动态规划 的方法来解决这个问题，但其实还能够进一步对改问题做优化。
在更新 dp 数组的时候，更新 第i号 行的值需要使用到 第i-1号 行的数据才可以，而更新完成 第i号 行后，就不会再次用到 第i-1号 行的数据了，所以并...</description>
      <content:encoded><![CDATA[
<p>哈喽 ~</p>
<p>你好啊 ~ 我是蓝莓 ~</p>
<h2>LeetCode 416 （状态压缩）</h2>
<p>在上一篇文章中，提到了怎么使用 动态规划 的方法来解决这个问题，但其实还能够进一步对改问题做优化。</p>
<p>在更新 <code>dp</code> 数组的时候，更新 <strong>第i号</strong> 行的值需要使用到 <strong>第i-1号</strong> 行的数据才可以，而更新完成 <strong>第i号</strong> 行后，就不会再次用到 <strong>第i-1号</strong> 行的数据了，所以并不需要存储那么多的值，我们可以把 <strong>二维</strong> 的 <strong>dp</strong> 数组压缩成 <strong>一维</strong> 的 <strong>dp</strong> 数组。</p>
<p><strong>定义 dp 数组</strong></p>
<p><code>bool dp[C]</code></p>
<p><strong>修改状态转移方程</strong></p>
<p>在之前的状态转移方程式这样的：</p>
<p><code>dp[i][j] </code></p>
<p><code>= dp[i-1][j-nums[i]] || dp[i-1][j]</code></p>
<p>使用了一维的 <code>dp</code> 数组后：</p>
<p><code>dp[j] = dp[j-nums[i]] || dp[j]</code></p>
<p>你仔细想想，相信这个式子是非常好理解的 ~ 等号右边的 <code>dp[j]</code> 可以理解为旧的 <code>dp[j]</code>，它就相当于 <code>dp[i-1][j]</code>。等号左边的 <code>dp[j]</code> 是新一轮的 <code>dp[j]</code> 其实就相当于 <code>dp[i][j]</code>，但是为什么能够直接把新的 <code>dp[j]</code> 放在旧的 <code>dp[j]</code> 的位置呢？因为旧的 <code>dp[j]</code> 的值最后一次使用就是在计算新的 <code>dp[j]</code> 的时候，而此后再也不会被用到了。</p>
<p>这里所说到的最后一次使用是按照新的计算顺序而言的，下边就会说明新的计算顺序是怎样的。</p>
<p><strong>如何更新 dp 数组</strong></p>
<p>在更新一维 <strong>dp</strong> 数组的时候就不能像二维那样的顺序来更新了，因为新的 <code>dp[j]</code> 的值取决于旧的<code>dp[j]</code> 和 <code>dp[j-nums[i]]</code> 如果更新 <strong>dp</strong> 数组是按照从左到右进行更新的话，计算靠右的值需要用到左边的值，而左边是先被更新的，所以就已经被覆盖了。</p>
<p>那么很简单的，我们只需要按照从右到左的顺序进行计算并且更新一维的 <strong>dp</strong> 数组就可以了</p>
<p>到这里思考一下，为什么这种优化方式叫做 <strong>状态压缩</strong> 呢，相信聪明的你也看出来了，<strong>dp</strong> 数组占用的空间少了很多，少存了很多的中间状态的值。少了就是压缩了嘛 ~</p>
<h2>完整版代码</h2>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool canPartition(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        int sum = 0;</span>
<span class="line">        for(int num : nums)</span>
<span class="line">            sum += num;</span>
<span class="line"></span>
<span class="line">        // sum 是奇数的时候是不可能分割的</span>
<span class="line">        if(sum % 2 != 0) return false;</span>
<span class="line"></span>
<span class="line">        // [0...nums.size()-1] 数值</span>
<span class="line">        // [0...C] 容量</span>
<span class="line">        int C = sum / 2;</span>
<span class="line"></span>
<span class="line">        // 容量 [0...C]</span>
<span class="line">        int dp[C+1];</span>
<span class="line"></span>
<span class="line">        // 处理仅考虑 0 号元素的情况</span>
<span class="line">        dp[0] = true; // 选择不装 0 号元素可装满</span>
<span class="line">        for(int j = 1 ; j &lt;= C ; ++j)</span>
<span class="line">            dp[j] = false;</span>
<span class="line">        // 该位置可装满</span>
<span class="line">        if(nums[0] &lt;= C) dp[nums[0]] = true;</span>
<span class="line"></span>
<span class="line">        for(int i = 1 ; i &lt; nums.size() ; ++i) {</span>
<span class="line">            for(int j = C ; j &gt;= 0 ; --j) {</span>
<span class="line">                // 没办法装入 i 号元素的时候</span>
<span class="line">                // dp[j] 的值不变</span>
<span class="line">                if(j &gt;= nums[i]) {</span>
<span class="line">                    dp[j] = dp[j] || dp[j-nums[i]];</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return dp[C];</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>如何写出正确的代码</title>
      <link>https://blueberry-universe.cn/2024-08-23-00/</link>
      <guid>https://blueberry-universe.cn/2024-08-23-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">如何写出正确的代码</source>
      <description>如何写出正确的代码
你好啊，我是蓝莓。
在这片文章中，通过二分查找来聊一聊如何写出正确的代码。
什么二分查找？
二分查找的思想不难理解，在一个有序数组中，我们要寻找 target，我们直接将该数组一分为二，直接去对比中间位置的那个值是不是我们要找的值。

如果该数组正中间的值  v刚刚好就是我们要找的值的话，那么皆大欢喜，我们已经找到了这个值所在数组中...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓。</p>
<p>在这片文章中，通过二分查找来聊一聊如何写出正确的代码。</p>
<h2>什么二分查找？</h2>
<p>二分查找的思想不难理解，在一个有序数组中，我们要寻找 target，我们直接将该数组一分为二，直接去对比中间位置的那个值是不是我们要找的值。</p>
<ol>
<li>如果该数组正中间的值  <code>v</code>刚刚好就是我们要找的值的话，那么皆大欢喜，我们已经找到了这个值所在数组中的位置了。</li>
<li>如果我们要找的值 <code>target &gt; v</code> 那么我们就直接丢弃数组左边的那部分值，直接去数组的右边进行搜索。</li>
<li>如果我们要找的值 <code>target &lt; v</code> 那么我们就直接丢弃数组的右边的那部分值，直接去数组的左边进行搜索。</li>
</ol>
<p></p>
<p>我们只需要不断的重复刚才的过程，如果 <code>target</code> 存在于该数组中的话，我们一定是能查找到的，如果这个值不在数组中的话，随着我们搜索的推进，我们可搜索的范围会越来越小，直到没有内容可以搜索，这时候就说明 <code>target</code> 不存在于该数组中。</p>
<h2>循环不变量</h2>
<p>有一个很专业的名词叫 <code>循环不变量</code>，虽然某些变量的值是一直在改变的，但是这个变量的定义是一直保持不变的，那么我们来看看二分搜索中的循环不变量是什么？</p>
<p>在这里，我定义一个函数 <code>binarySearch</code> 并且传递三个参数</p>
<ol>
<li>arr 这是我们要搜索的数组</li>
<li>arr 数组中包含 n 个元素，也就是 <code>arr[0]</code> 到 <code>arr[n-1]</code> 都是可以读取到的</li>
<li>target 是我们要搜索的目标值，判断 arr 中是否包含 target</li>
</ol>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 在包含 n 个元素的数组 arr 中寻找目标值 target 的下标</span>
<span class="line">int binarySearch(const int* arr, int n, int target) {</span>
<span class="line">    // 在区间 [l...r] 这个区间内寻找 target</span>
<span class="line">    int l = 0, r = n-1;</span>
<span class="line"></span>
<span class="line">    // 在没有找到并且 [l...r] 区间内仍然是有元素的情况下继续查找</span>
<span class="line">    while( l &lt;= r ) {</span>
<span class="line">        int mid = (l+r) / 2;</span>
<span class="line">        if( arr[mid] == target ) {</span>
<span class="line">            return mid;</span>
<span class="line">        } else if( target &gt; arr[mid] ) {</span>
<span class="line">            l = mid+1;</span>
<span class="line">        } else {</span>
<span class="line">            // target &lt; arr[mid]</span>
<span class="line">            r = mid-1;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    return -1;  // 如果循环都结束了，说明还是没有找到，那么返回 -1 代表失败</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接着让我们一点一点的来看：</p>
<p>这里的 <code>l</code> 和 <code>r</code> 分别代表我们要搜索的位于 <code>arr</code> 数组中的氛围，我们要在区间 <code>[l...r]</code> 这个范围内寻找 target；这里的 <code>l</code> 和 <code>r</code> 就是我们要维护的循环不变量，因为我们始终要在 <code>[l...r]</code> 这样一个闭区间内寻找 <code>target</code></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    // 在区间 [l...r] 这个区间内寻找 target</span>
<span class="line">    int l = 0, r = n-1;</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>循环进行的条件：</p>
<p>什么情况下，循环要继续进行下去呢？那就是，我们依然没有寻找到 <code>target</code> 并且 <code>[l...r]</code> 这个区间内依然是有元素的，这种情况就要让循环继续下去。即使当 <code>l 等于 r</code> 的时候，<code>[l...r]</code> 这个区间内依然是拥有一个元素的，所以，我们依然还是可以继续让循环进行下去的，因此循环的条件应该是 <code>l &lt;= r</code></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    // 在没有找到并且 [l...r] 区间内仍然是有元素的情况下继续查找</span>
<span class="line">	while( l &lt;= r ) {</span>
<span class="line"></span>
<span class="line">    }</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接着，我们就来看循环内部的语句了，在本轮循环中共有三种情况，首先我们先计算出 <code>[l...r]</code> 这个范围内正中间的下标是什么，得到 <code>mid</code>，随后这三种情况分别是：</p>
<ol>
<li><code>arr[mid]</code> 就是我们要找的 <code>target</code></li>
<li>我们要找的 <code>target</code> 比 <code>arr[mid]</code> 还要大一些，这时候我们可以寻找右边的那部分</li>
<li>我们要找的 <code>target</code> 比 <code>arr[mid]</code> 还要小一些，这时候我们可以寻找左边的那部分</li>
</ol>
<p>后面的那两种情况，我们只需要简单的通过修改 <code>l或r</code> 的值就可以了，通过修改搜索区间的索引来维持这件事情。</p>
<p>在修改搜索区间的时候，你可以发现，我们都跳过了 <code>mid</code> 这个位置，也就是说，如果当前的 <code>arr[mid]</code> 不是我们要找的那个值，在下一次的搜索区间中将不会包含 <code>mid</code> 这个下标了，这里也恰到好处的维护了 <code>[l...r]</code> 这个区间就是我们将要搜索的范围这样一个循环不变量。就是说：<code>l</code> 和 <code>r</code> 这两个变量的值虽然在改变，但是它们的定义始终不变。</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">    while( l &lt;= r ) {</span>
<span class="line">        int mid = (l+r) / 2;</span>
<span class="line">        if( arr[mid] == target ) {</span>
<span class="line">            return mid;  // 如果找到了就直接返回</span>
<span class="line">        } else if( target &gt; arr[mid] ) {</span>
<span class="line">            l = mid+1;</span>
<span class="line">        } else {</span>
<span class="line">            // target &lt; arr[mid]</span>
<span class="line">            r = mid-1;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>测试</h2>
<p>我们通过写一个简单的代码，来测试一下我们的算法</p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">int main() {</span>
<span class="line"></span>
<span class="line">    const int n = 1000000;</span>
<span class="line">    int* arr = new int[n];</span>
<span class="line"></span>
<span class="line">    // 生成一个包含 n 个元素的完全有序的数组 arr</span>
<span class="line">    for(int i = 0; i &lt; n; i++) {</span>
<span class="line">        arr[i] = i;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    // 对 arr 中的每一次元素都进行查找</span>
<span class="line">    clock_t start_time = clock();</span>
<span class="line">    for(int i = 0; i &lt; n; i++) {</span>
<span class="line">        assert(i == binarySearch(arr, n, i));</span>
<span class="line">    }</span>
<span class="line">    clock_t end_time = clock();</span>
<span class="line"></span>
<span class="line">    // 计算查找 n 次所需要的时间</span>
<span class="line">    cout &lt;&lt; &quot;Time: &quot; &lt;&lt; double(end_time - start_time) / CLOCKS_PER_SEC &lt;&lt; endl;</span>
<span class="line">    cout &lt;&lt; &quot;done!&quot; &lt;&lt; endl;</span>
<span class="line">    return 0;</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>运行结果：</p>
<p>在包含 100w 个元素的数组中进行 100w 次二分查找，在我的计算机上共使用了 0.08秒的时间；</p>
<p></p>
<h2>完整代码</h2>
<p>本文采用了 <code>C++</code></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">#include &lt;iostream&gt;</span>
<span class="line">#include &lt;cassert&gt;</span>
<span class="line">#include &lt;ctime&gt;</span>
<span class="line">using namespace std;</span>
<span class="line"></span>
<span class="line">// 在包含 n 个元素的数组 arr 中寻找目标值 target 的下标</span>
<span class="line">int binarySearch(const int* arr, int n, int target) {</span>
<span class="line">    // 在区间 [l...r] 这个区间内寻找 target</span>
<span class="line">    int l = 0, r = n-1;</span>
<span class="line"></span>
<span class="line">    // 在没有找到并且 [l...r] 区间内仍然是有元素的情况下继续查找</span>
<span class="line">    while( l &lt;= r ) {</span>
<span class="line">        int mid = (l+r) / 2;</span>
<span class="line">        if( arr[mid] == target ) {</span>
<span class="line">            return mid;</span>
<span class="line">        } else if( target &gt; arr[mid] ) {</span>
<span class="line">            l = mid+1;</span>
<span class="line">        } else {</span>
<span class="line">            // target &lt; arr[mid]</span>
<span class="line">            r = mid-1;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    return -1;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">int main() {</span>
<span class="line"></span>
<span class="line">    const int n = 1000000;</span>
<span class="line">    int* arr = new int[n];</span>
<span class="line"></span>
<span class="line">    // 生成一个包含 n 个元素的完全有序的数组 arr</span>
<span class="line">    for(int i = 0; i &lt; n; i++) {</span>
<span class="line">        arr[i] = i;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    // 对 arr 中的每一次元素都进行查找</span>
<span class="line">    clock_t start_time = clock();</span>
<span class="line">    for(int i = 0; i &lt; n; i++) {</span>
<span class="line">        assert(i == binarySearch(arr, n, i));</span>
<span class="line">    }</span>
<span class="line">    clock_t end_time = clock();</span>
<span class="line"></span>
<span class="line">    // 计算查找 n 次所需要的时间</span>
<span class="line">    cout &lt;&lt; &quot;Time: &quot; &lt;&lt; double(end_time - start_time) / CLOCKS_PER_SEC &lt;&lt; endl;</span>
<span class="line">    cout &lt;&lt; &quot;done!&quot; &lt;&lt; endl;</span>
<span class="line">    return 0;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0283 移动零</title>
      <link>https://blueberry-universe.cn/2024-12-16-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-16-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0283 移动零</source>
      <description>0283 移动零
题目描述

给定一个数组 nums，编写一个函数将所有 0 移动到数组的末尾，同时保持非零元素的相对顺序。
请注意 ，必须在不复制数组的情况下原地对数组进行操作。
示例 1:

示例 2:

提示:

1 &amp;lt;= nums.length &amp;lt;= 104
-231 &amp;lt;= nums[i] &amp;lt;= 231 - 1

代码:...</description>
      <content:encoded><![CDATA[
<h2>题目描述</h2>
<blockquote>
<p>给定一个数组 <code>nums</code>，编写一个函数将所有 <code>0</code> 移动到数组的末尾，同时保持非零元素的相对顺序。</p>
<p><strong>请注意</strong> ，必须在不复制数组的情况下原地对数组进行操作。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: nums = [0,1,0,3,12]</span>
<span class="line">输出: [1,3,12,0,0]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: nums = [0]</span>
<span class="line">输出: [0]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示</strong>:</p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 104</code></li>
<li><code>-231 &lt;= nums[i] &lt;= 231 - 1</code></li>
</ul>
<p><strong>代码</strong>:</p>
<div class="language-C++ line-numbers-mode" data-highlighter="prismjs" data-ext="C++"><pre><code class="language-C++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void moveZeroes(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        </span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></blockquote>
<h2>方法一</h2>
<p><strong>思路</strong></p>
<p>方法一和题目的要求不太符合，题目说了：在不复制数组的情况下原地完成，咱们先使用一个更简单的方法来实现</p>
<p>把所有的非零元素从 nums 里面拿出来放在 nonZeroNums 中，然后再把 nonZeroNums 中的元素放回 nums，nums 的其他元素赋值为 0</p>
<p><strong>代码实现</strong></p>
<div class="language-C++ line-numbers-mode" data-highlighter="prismjs" data-ext="C++"><pre><code class="language-C++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void moveZeroes(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        vector&lt;int&gt; nonZeroNums;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            if( nums[i] != 0 )</span>
<span class="line">                nonZeroNums.push_back( nums[i] );</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nonZeroNums.size() ; i++ ) {</span>
<span class="line">            nums[i] = nonZeroNums[i];</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = nonZeroNums.size() ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            nums[i] = 0;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>方法二</h2>
<p><strong>思路</strong></p>
<ul>
<li>
<p>维护一个区间，我们规定 nums 数组的 <code>[0...r)</code> 表示的是非零元素的部分，在算法初始化的时候 r 的值等于 0，所以这样一个左闭右开的区间再算法一开始表达的是一个空区间的意思。</p>
</li>
<li>
<p>使用一个索引 i 从 0 开始遍历整个 nums 数组，如果 i 遇到的这个位置的元素是非零元素，那么就把这个元素放在 r 索引的位置，然后再让 r 索引向右移动一个位置，扩大非零元素的区间（因为我们向非零元素的区间添加了一个非零元素，当然就要扩大啦），你可以发现 r 这个索引指向的始终是下一次我们发现非零元素的时候要放的位置。</p>
</li>
<li>
<p>最后，我们全都遍历完了，我们就要把 nums 数组从 r 一直到最后的全部元素赋值为 0</p>
</li>
</ul>
<p><strong>代码实现</strong></p>
<div class="language-C++ line-numbers-mode" data-highlighter="prismjs" data-ext="C++"><pre><code class="language-C++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void moveZeroes(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        // [0...r) 是非零元素的区间</span>
<span class="line">        // [0...0) 表示空区间</span>
<span class="line"></span>
<span class="line">        int r = 0;</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            if( nums[i] != 0 ) {</span>
<span class="line">                nums[r++] = nums[i];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = r ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            nums[i] = 0;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>方法三</h2>
<p><strong>思路</strong></p>
<ul>
<li>在方法二中你可能会发现，最后赋值 0 的过程有些多余，所以我们还可以改一下，写成方法三的样子，我们直接在遍历非零元素的时候就把 0 给赋值上去，要注意 r 和 i 如果指向的是同一个元素的话，我们是不能赋值为 0 的，不然我们就把非零元素给覆盖掉了</li>
</ul>
<p><strong>代码实现</strong></p>
<div class="language-C++ line-numbers-mode" data-highlighter="prismjs" data-ext="C++"><pre><code class="language-C++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void moveZeroes(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        // [0...r) 是非零元素的区间</span>
<span class="line">        // [0...0) 表示空区间</span>
<span class="line"></span>
<span class="line">        int r = 0;</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            if( nums[i] != 0 ) {</span>
<span class="line">                nums[r] = nums[i];</span>
<span class="line">                if( r != i) {</span>
<span class="line">                    nums[i] = 0;</span>
<span class="line">                }</span>
<span class="line">                r++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0027 移动元素</title>
      <link>https://blueberry-universe.cn/2024-12-17-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-17-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0027 移动元素</source>
      <description>0027 移动元素
你好啊，我是蓝莓，今天是每日一题的第 2 天。
题目清单：https://blueberry-universe.cn/lc/index.html
引用力扣题目：https://leetcode.cn/problems/remove-element/description/
题目描述
给你一个数组 nums 和一个值 val，你需要 ...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 2 天。</p>
<p>题目清单：https://blueberry-universe.cn/lc/index.html</p>
<p>引用力扣题目：https://leetcode.cn/problems/remove-element/description/</p>
<h2>题目描述</h2>
<p>给你一个数组 <code>nums</code> 和一个值 <code>val</code>，你需要 <strong><a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank" rel="noopener noreferrer">原地</a></strong> 移除所有数值等于 <code>val</code> 的元素。元素的顺序可能发生改变。然后返回 <code>nums</code> 中与 <code>val</code> 不同的元素的数量。</p>
<p>假设 <code>nums</code> 中不等于 <code>val</code> 的元素数量为 <code>k</code>，要通过此题，您需要执行以下操作：</p>
<ul>
<li>更改 <code>nums</code> 数组，使 <code>nums</code> 的前 <code>k</code> 个元素包含不等于 <code>val</code> 的元素。<code>nums</code> 的其余元素和 <code>nums</code> 的大小并不重要。</li>
<li>返回 <code>k</code>。</li>
</ul>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [3,2,2,3], val = 3</span>
<span class="line">输出：2, nums = [2,2,_,_]</span>
<span class="line">解释：你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。</span>
<span class="line">你在返回的 k 个元素之外留下了什么并不重要（因此它们并不计入评测）。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [0,1,2,2,3,0,4,2], val = 2</span>
<span class="line">输出：5, nums = [0,1,4,0,3,_,_,_]</span>
<span class="line">解释：你的函数应该返回 k = 5，并且 nums 中的前五个元素为 0,0,1,3,4。</span>
<span class="line">注意这五个元素可以任意顺序返回。</span>
<span class="line">你在返回的 k 个元素之外留下了什么并不重要（因此它们并不计入评测）。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>0 &lt;= nums.length &lt;= 100</code></li>
<li><code>0 &lt;= nums[i] &lt;= 50</code></li>
<li><code>0 &lt;= val &lt;= 100</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<p>这个题目和 <a href="https://mp.weixin.qq.com/s/6dayzKs2SNl0-nHz9pyP6g" target="_blank" rel="noopener noreferrer">「每日一题」力扣 283 移动零</a> 使用的方法是类似的，我们都是维护一个一开始为空的区间，然后在不断的扫描数组同时维护好我们定义的那个最终答案的区间。</p>
<ul>
<li>
<p>维护 nums 数组的区间 [0...k) 为不等于 val 元素的区间</p>
</li>
<li>
<p>由于 区间 [0...k)  装的是不等于 val 的值，所以在算法开始前，我们应该让 k 的值为 0 这样就表示我们在算法开始之前，这个区间内不包含任何元素，每当我们发现一个不等于 val 元素的值后就把这个值和索引 k 所在的值进行交换并让 k 向右移动一个位置</p>
</li>
<li>
<p>在代码实现中有一点是判断 i 和 k 是否相同，如果 i 等于 k 的话，那么我们就没有必要让 <code>nums[i]</code> 和 <code>nums[k]</code> 的值进行交换了，我们只需要让 k 向右移动一个位置就可以让这个元素放进我们维护的区间里面了</p>
</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">(</span><span class="token builtin">object</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">removeElement</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token triple-quoted-string string">"""</span>
<span class="line">        :type nums: List[int]</span>
<span class="line">        :type val: int</span>
<span class="line">        :rtype: int</span>
<span class="line">        """</span></span>
<span class="line">        <span class="token comment"># 维护区间 [0...k) 为非 val 元素的区间</span></span>
<span class="line">        <span class="token comment"># 初始化 k 为 0 则 [0...0) 代表为一个空区间</span></span>
<span class="line">        k <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">        <span class="token comment"># 遍历 nums 列表</span></span>
<span class="line">        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> val<span class="token punctuation">:</span></span>
<span class="line">                <span class="token keyword">if</span> i <span class="token operator">!=</span> k<span class="token punctuation">:</span></span>
<span class="line">                    nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span></span>
<span class="line">                k <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> k</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-C++ line-numbers-mode" data-highlighter="prismjs" data-ext="C++"><pre><code class="language-C++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int removeElement(vector&lt;int&gt;&amp; nums, int val) {</span>
<span class="line">        // [0...k) 区间维护不等于 val 的元素</span>
<span class="line">        int k = 0;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            if( nums[i] != val ) {</span>
<span class="line">                if( k != i ) {</span>
<span class="line">                    swap(nums[k], nums[i]);</span>
<span class="line">                } </span>
<span class="line">                k++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return k;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">removeElement</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">,</span> <span class="token keyword">int</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">for</span><span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;</span> nums<span class="token punctuation">.</span>length <span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> val <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">if</span><span class="token punctuation">(</span> i <span class="token operator">!=</span> k <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                    <span class="token keyword">int</span> temp <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                    nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                    nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> temp<span class="token punctuation">;</span></span>
<span class="line">                <span class="token punctuation">}</span></span>
<span class="line">                k<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> k<span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0026 删除有序数组中的重复项</title>
      <link>https://blueberry-universe.cn/2024-12-18-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-18-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0026 删除有序数组中的重复项</source>
      <description>0026 删除有序数组中的重复项
你好啊，我是蓝莓，今天是每日一题的第 3 天。
我的博客：https://blueberry-universe.cn/lc/index.html
力扣题目：https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/
题目描述...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 3 天。</p>
<p>我的博客：https://blueberry-universe.cn/lc/index.html</p>
<p>力扣题目：https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/</p>
<h2>题目描述</h2>
<p>给你一个 <strong>非严格递增排列</strong> 的数组 <code>nums</code> ，请你**<a href="http://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank" rel="noopener noreferrer"> 原地</a>** 删除重复出现的元素，使每个元素 <strong>只出现一次</strong> ，返回删除后数组的新长度。元素的 <strong>相对顺序</strong> 应该保持 <strong>一致</strong> 。然后返回 <code>nums</code> 中唯一元素的个数。</p>
<p>考虑 <code>nums</code> 的唯一元素的数量为 <code>k</code> ，你需要做以下事情确保你的题解可以被通过：</p>
<ul>
<li>更改数组 <code>nums</code> ，使 <code>nums</code> 的前 <code>k</code> 个元素包含唯一元素，并按照它们最初在 <code>nums</code> 中出现的顺序排列。<code>nums</code> 的其余元素与 <code>nums</code> 的大小不重要。</li>
<li>返回 <code>k</code> 。</li>
</ul>
<p><strong>判题标准:</strong></p>
<p>系统会用下面的代码来测试你的题解:</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">int[] nums = [...]; // 输入数组</span>
<span class="line">int[] expectedNums = [...]; // 长度正确的期望答案</span>
<span class="line"></span>
<span class="line">int k = removeDuplicates(nums); // 调用</span>
<span class="line"></span>
<span class="line">assert k == expectedNums.length;</span>
<span class="line">for (int i = 0; i &lt; k; i++) {</span>
<span class="line">    assert nums[i] == expectedNums[i];</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果所有断言都通过，那么您的题解将被 <strong>通过</strong>。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,1,2]</span>
<span class="line">输出：2, nums = [1,2,_]</span>
<span class="line">解释：函数应该返回新的长度 2 ，并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [0,0,1,1,1,2,2,3,3,4]</span>
<span class="line">输出：5, nums = [0,1,2,3,4]</span>
<span class="line">解释：函数应该返回新的长度 5 ， 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 3 * 104</code></li>
<li><code>-104 &lt;= nums[i] &lt;= 104</code></li>
<li><code>nums</code> 已按 <strong>非严格递增</strong> 排列</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<p>同样的，这个题目和之前写过的两个题目的解决方法是一样的，这两个题目的链接如下：</p>
<p><a href="https://mp.weixin.qq.com/s/6dayzKs2SNl0-nHz9pyP6g" target="_blank" rel="noopener noreferrer">「每日一题」力扣 283 移动零</a></p>
<p><a href="https://mp.weixin.qq.com/s/BjGwnxNO1I_NVJpM_86ZYQ" target="_blank" rel="noopener noreferrer">「每日一题」力扣 27 移动元素</a></p>
<ul>
<li>维护 <code>nums[0...k)</code> 为不重复的元素所在区间</li>
<li>索引 <code>k</code> 在算法初始时应赋值为 0 ； 代表算法开始前， <code>nums[0...k)</code> 是一个空区间</li>
<li>由于 <code>nums</code> 数组是一个非严格的递增序列（当出现相邻元素的时候，这段区间就是所谓的非严格递增了，同时也告诉我们，重复的元素在 nums 数组中都是相邻的），所以使用索引 <code>i</code>  遍历整个 nums 数组，每当我们发现 <code>i</code> 遍历到的元素和 <code>nums[0...k)</code> 这个区间的最后一个元素不相等的时候就说明我们找到了一个新的不重复的元素，这时候我们只需要把这个新的元素纳入到 <code>nums[0...k)</code> 这个区间就可以了</li>
<li><code>nums[0...k)</code> 区间的最后一个元素其实就是 <code>nums[k-1]</code> 这个元素</li>
<li>需要注意的是：如果 <code>nums[0...k)</code> 这个区间一开始为空的话，也就是说 <code>k = 0</code>，那么 <code>nums[k-1]</code> 就是 <code>nums[-1]</code> 了，这显然是越界的。因此，除了在 <code>nums[i] != nums[k-1]</code> 的时候可以在区间中纳入一个新的不重复元素外，还可以在 <code>k = 0 </code>  的时候在我们维护的区间中纳入一个新的元素，这时候，你可以选择直接让 <code>k</code> 增加 1，或者你也可以在代码中保持统一写成 <code>nums[k] = nums[i]</code> 的形式 （这就相当于自己赋值给了自己嘛），然后再让 <code>k</code> 增加 1，其实都是一样的。</li>
<li>根据题目描述中的测试方式来看，这个题目只需要将不重复的元素放在 nums 数组的左侧就可以了，并不需要我们清除那些重复的元素，所以我们可以不对 nums 数组的大小进行调整</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">(</span><span class="token builtin">object</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">removeDuplicates</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token triple-quoted-string string">"""</span>
<span class="line">        :type nums: List[int]</span>
<span class="line">        :rtype: int</span>
<span class="line">        """</span></span>
<span class="line">        k <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> k <span class="token operator">==</span> <span class="token number">0</span> <span class="token keyword">or</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> nums<span class="token punctuation">[</span>k<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">                k <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">        </span>
<span class="line">        <span class="token keyword">return</span> k</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int removeDuplicates(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        // 维护 nums[0...k) 装在不重复的元素所在区间</span>
<span class="line"></span>
<span class="line">        int k = 0;</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            if( k == 0 || nums[i] != nums[k-1] ) {</span>
<span class="line">                nums[k++] = nums[i];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line">        return k;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">removeDuplicates</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">for</span><span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;</span> nums<span class="token punctuation">.</span>length <span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> k <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">||</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> nums<span class="token punctuation">[</span>k<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                nums<span class="token punctuation">[</span>k<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> k<span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">removeDuplicates</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">    k <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token function">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">if</span> k <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">||</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> nums<span class="token punctuation">[</span>k<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token punctuation">{</span></span>
<span class="line">            nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            k <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> k<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0080 删除有序数组中的重复项 II</title>
      <link>https://blueberry-universe.cn/2024-12-19-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-19-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0080 删除有序数组中的重复项 II</source>
      <description>0080 删除有序数组中的重复项 II
你好啊，我是蓝莓，今天是每日一题的第 4 天。
题目清单：https://blueberry-universe.cn/lc/index.html
引用力扣题目：https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/descripti...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 4 天。</p>
<p><strong>题目清单</strong>：https://blueberry-universe.cn/lc/index.html</p>
<p><strong>引用力扣题目</strong>：https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/description/</p>
<h2>题目描述</h2>
<p>给你一个有序数组 <code>nums</code> ，请你**<a href="http://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank" rel="noopener noreferrer"> 原地</a>** 删除重复出现的元素，使得出现次数超过两次的元素<strong>只出现两次</strong> ，返回删除后数组的新长度。</p>
<p>不要使用额外的数组空间，你必须在 <strong><a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank" rel="noopener noreferrer">原地 </a>修改输入数组</strong> 并在使用 O(1) 额外空间的条件下完成。</p>
<p><strong>说明：</strong></p>
<p>为什么返回数值是整数，但输出的答案是数组呢？</p>
<p>请注意，输入数组是以**「引用」**方式传递的，这意味着在函数里修改输入数组对于调用者是可见的。</p>
<p>你可以想象内部操作如下:</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">// nums 是以“引用”方式传递的。也就是说，不对实参做任何拷贝</span>
<span class="line">int len = removeDuplicates(nums);</span>
<span class="line"></span>
<span class="line">// 在函数里修改输入数组对于调用者是可见的。</span>
<span class="line">// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。</span>
<span class="line">for (int i = 0; i &lt; len; i++) {</span>
<span class="line">    print(nums[i]);</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,1,1,2,2,3]</span>
<span class="line">输出：5, nums = [1,1,2,2,3]</span>
<span class="line">解释：函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3。 不需要考虑数组中超出新长度后面的元素。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [0,0,1,1,1,1,2,3,3]</span>
<span class="line">输出：7, nums = [0,0,1,1,2,3,3]</span>
<span class="line">解释：函数应返回新长度 length = 7, 并且原数组的前七个元素被修改为 0, 0, 1, 1, 2, 3, 3。不需要考虑数组中超出新长度后面的元素。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 3 * 104</code></li>
<li><code>-104 &lt;= nums[i] &lt;= 104</code></li>
<li><code>nums</code> 已按升序排列</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<p>这个题目和以下三个题目的思路是差不多的，链接如下：</p>
<p><a href="https://mp.weixin.qq.com/s/6dayzKs2SNl0-nHz9pyP6g" target="_blank" rel="noopener noreferrer"><strong>「每日一题」力扣 283 移动零</strong></a></p>
<p><a href="https://mp.weixin.qq.com/s/BjGwnxNO1I_NVJpM_86ZYQ" target="_blank" rel="noopener noreferrer"><strong>「每日一题」力扣 27 移动元素</strong></a></p>
<p><a href="https://mp.weixin.qq.com/s/qI9AiL30bZzI0DWuF2meTQ" target="_blank" rel="noopener noreferrer"><strong>「每日一题」力扣 26 删除有序数组中的重复项</strong></a></p>
<ul>
<li><code>nums[0...k)</code> 区间为这个题目的结果，这个区间中允许每个数值最多出现 2 次，超过 2 次的是不会出现在这个区间中的</li>
<li>k<code> 的初始值依然为 0，这代表在算法开始之前，</code>nums[0...k)`  这个区间是一个空区间</li>
<li>用索引 <code>i</code> 遍历 <code>nums</code> 数组，每当我们发现一个数值实在 <code>nums[0...k)</code> 区间中出现的次数不超过 2 次的，我们就把这个元素纳入到 <code>nums[0...k)</code> 区间中
-最后一个问题就是：我们如何判断当前遍历到的元素 <code>nums[i]</code> 在当前的区间 <code>nums[0...k)</code> 中出现的次数是小于 2 次的 ？ 因为题目给出的数组 <code>nums</code> 的元素是按照从小到大的顺序排序好的，所以如果是连续出现的数值，必然被我们纳入到 <code>nums[0...k)</code> 区间中也是连续的，所以我们可以直接判断：是不是 <code>nums[k-2] != nums[i]</code>。如果 是不是 <code>nums[k-2] != nums[i]</code> 是成立的，那么我们就可以把当前这个元素纳入到 <code>nums[0...k)</code> 区间中了。<code>nums[k-2]</code> 代表的就是这个区间中的倒数第二个元素，当我们发现 <code>nums[i]</code> 和倒数第一个元素相等是没关系的，因为在我们维护的区间中每个元素最多可以出现两次，可是一旦这个元素和倒数第二个元素相等，那就不行了。</li>
<li>越界处理：由于当 <code>k == 0</code> 或者 <code>k == 1</code> 的时候 <code>nums[k-2]</code> 的访问是越界的，然而这个题目又允许每个元素最多可以出现两次，所以当当 <code>k == 0</code> 或者 <code>k == 1</code> 的时候直接无脑将 <code>nums[i]</code> 纳入到我们维护的区间即可。</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">removeDuplicates</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">int</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token comment"># 维护 nums[0...k) 区间为出现小于等于 2 次的元素</span></span>
<span class="line">        k <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            <span class="token comment"># 只要 nums[i] 不等于 nums[0...k) 区间中的倒数第2个元素即可</span></span>
<span class="line">            <span class="token keyword">if</span> k <span class="token operator">==</span> <span class="token number">0</span> <span class="token keyword">or</span> k <span class="token operator">==</span> <span class="token number">1</span> <span class="token keyword">or</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> nums<span class="token punctuation">[</span>k<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">                k <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> k</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int removeDuplicates(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        // 维护 nums[0...k) 区间为出现小于等于 2 次的元素</span>
<span class="line">        int k = 0;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            // 只要 nums[i] 不等于 nums[0...k) 区间中的倒数第2个元素即可</span>
<span class="line">            if( k == 0 || k == 1 || nums[i] != nums[k-2]) {</span>
<span class="line">                nums[k++] = nums[i];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return k;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">removeDuplicates</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 维护 nums[0...k) 区间为出现小于等于 2 次的元素</span></span>
<span class="line">        <span class="token keyword">int</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">for</span><span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;</span> nums<span class="token punctuation">.</span>length <span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// 只要 nums[i] 不等于 nums[0...k) 区间中的倒数第2个元素即可</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> k <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">||</span> k <span class="token operator">==</span> <span class="token number">1</span> <span class="token operator">||</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> nums<span class="token punctuation">[</span>k<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                nums<span class="token punctuation">[</span>k<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> k<span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">removeDuplicates</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 维护 nums[0...k) 区间为出现小于等于 2 次的元素</span></span>
<span class="line">    k <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token function">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 只要 nums[i] 不等于 nums[0...k) 区间中的倒数第2个元素即可</span></span>
<span class="line">        <span class="token keyword">if</span> k <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">||</span> k <span class="token operator">==</span> <span class="token number">1</span> <span class="token operator">||</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">!=</span> nums<span class="token punctuation">[</span>k<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token punctuation">{</span></span>
<span class="line">            nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">            k <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> k<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0075 颜色分类</title>
      <link>https://blueberry-universe.cn/2024-12-20-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-20-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0075 颜色分类</source>
      <description>0075 颜色分类
你好啊，我是蓝莓，今天是每日一题的第 5 天。
题目清单：https://blueberry-universe.cn/lc/index.html
引用力扣题目：https://leetcode.cn/problems/sort-colors/description/
题目描述
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nu...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 5 天。</p>
<p><strong>题目清单</strong>：https://blueberry-universe.cn/lc/index.html</p>
<p><strong>引用力扣题目</strong>：https://leetcode.cn/problems/sort-colors/description/</p>
<h2>题目描述</h2>
<p>给定一个包含红色、白色和蓝色、共 <code>n</code> 个元素的数组 <code>nums</code> ，<strong><a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95" target="_blank" rel="noopener noreferrer">原地</a></strong> 对它们进行排序，使得相同颜色的元素相邻，并按照红色、白色、蓝色顺序排列。</p>
<p>我们使用整数 <code>0</code>、 <code>1</code> 和 <code>2</code> 分别表示红色、白色和蓝色。</p>
<p>必须在不使用库内置的 sort 函数的情况下解决这个问题。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [2,0,2,1,1,0]</span>
<span class="line">输出：[0,0,1,1,2,2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [2,0,1]</span>
<span class="line">输出：[0,1,2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>n == nums.length</code></li>
<li><code>1 &lt;= n &lt;= 300</code></li>
<li><code>nums[i]</code> 为 <code>0</code>、<code>1</code> 或 <code>2</code></li>
</ul>
<p><strong>进阶：</strong></p>
<ul>
<li>你能想出一个仅使用常数空间的一趟扫描算法吗？</li>
</ul>
<h2>方法一</h2>
<p><strong>思路</strong></p>
<ul>
<li>第一种方法，我们可以使用计数排序的思路</li>
<li>遍历 <code>nums</code> 数组，统计出 <code>0, 1, 2</code> 三个数值出现的次数分别是多少</li>
<li>然后按照统计出的出现的次数，依次填回到 <code>nums</code> 数组中即可</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">sortColors</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token boolean">None</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token triple-quoted-string string">"""</span>
<span class="line">        Do not return anything, modify nums in-place instead.</span>
<span class="line">        """</span></span>
<span class="line">        <span class="token comment"># 使用 counter 记录 0 1 2 分别出现的次数</span></span>
<span class="line">        counter <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span></span>
<span class="line"></span>
<span class="line">        <span class="token comment"># 统计 0 1 2 出现的次数</span></span>
<span class="line">        <span class="token keyword">for</span> num <span class="token keyword">in</span> nums<span class="token punctuation">:</span></span>
<span class="line">            counter<span class="token punctuation">[</span>num<span class="token punctuation">]</span> <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        i <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        <span class="token keyword">for</span> num <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>counter<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">for</span> _ <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>counter<span class="token punctuation">[</span>num<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> num</span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void sortColors(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        // 使用 counter 记录 0 1 2 分别出现的次数</span>
<span class="line">        vector&lt;int&gt; counter(3, 0);</span>
<span class="line">		</span>
<span class="line">        // 统计 0 1 2 出现的次数</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            counter[nums[i]]++;</span>
<span class="line">        }</span>
<span class="line">		</span>
<span class="line">        // 记录当前填充到了 nums 数组的位置</span>
<span class="line">        int i = 0;</span>
<span class="line">        // num 从 0 取到 2</span>
<span class="line">        for( int num = 0 ; num &lt; counter.size() ; num++ ) {</span>
<span class="line">            // 填充 counter[num] 次 num 数值</span>
<span class="line">            for( int sz = 0 ; sz &lt; counter[num] ; sz++ ) {</span>
<span class="line">                // 每次填充一个数值之后就让 i 向后移动一下</span>
<span class="line">                nums[i++] = num;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">sortColors</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 使用 counter 记录 0 1 2 分别出现的次数</span></span>
<span class="line">        <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> counter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">		</span>
<span class="line">        <span class="token comment">// 统计 0 1 2 出现的次数</span></span>
<span class="line">        <span class="token keyword">for</span><span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;</span> nums<span class="token punctuation">.</span>length <span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            counter<span class="token punctuation">[</span>nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>  <span class="token comment">// 记录当前填充到了 nums 数组的位置</span></span>
<span class="line">        <span class="token keyword">for</span><span class="token punctuation">(</span> <span class="token keyword">int</span> num <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> num <span class="token operator">&lt;</span> counter<span class="token punctuation">.</span>length <span class="token punctuation">;</span> num<span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// 填充 counter[num] 次 num 数值</span></span>
<span class="line">            <span class="token keyword">for</span><span class="token punctuation">(</span> <span class="token keyword">int</span> sz <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> sz <span class="token operator">&lt;</span> counter<span class="token punctuation">[</span>num<span class="token punctuation">]</span> <span class="token punctuation">;</span> sz<span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// 每次填充一个数值之后就让 i 向后移动一下</span></span>
<span class="line">                nums<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> num<span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">sortColors</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span>  <span class="token punctuation">{</span></span>
<span class="line">    counter <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> num <span class="token operator">:=</span> <span class="token keyword">range</span> nums <span class="token punctuation">{</span></span>
<span class="line">        counter<span class="token punctuation">[</span>num<span class="token punctuation">]</span> <span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">for</span> num<span class="token punctuation">,</span> sz <span class="token operator">:=</span> <span class="token keyword">range</span> counter <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token number">0</span> <span class="token punctuation">;</span> k <span class="token operator">&lt;</span> sz <span class="token punctuation">;</span> k<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">            nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> num<span class="token punctuation">;</span></span>
<span class="line">            i <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>方法二</h2>
<p><strong>思路</strong></p>
<ul>
<li>第二种方法就是使用 <code>快速排序</code> 的三路快排中的 partition 步骤来实现</li>
<li><code>partition</code> 这一步做了什么 ？ 在快速排序中，我们首先会选择一个值 <code>v</code> ， 然后把小于 <code>v</code> 的值全部放在数组的左侧，等于 <code>v</code> 的值放在数组的中间，大于 <code>v</code> 的值放在数组的右侧；观察这个题目，其实也是需要将所有的数组分成三个部分，每个部分装载了不同的值，分别是 <code>0 1 2</code></li>
<li>那么，我们维护三个区间就可以了，每个区间装载不同的值</li>
<li>小于 <code>v</code> 的区间定义为：<code>nums[0...i)</code> ，这里 i 的初始值为 0</li>
<li>等于 <code>v</code> 的区间定义为：<code>nums[i...j)</code> ，这里 j 的初始值为 0</li>
<li>大于 <code>v</code> 的区间定义为：<code>nums(k...n-1]</code> ，这里的 k 初始化为 n-1； n 代表数组长度</li>
<li>使用索引 <code>cur</code> 遍历 <code>nums</code> 数组，每当我们遇到不同的值的时候，我们就将它放在不同的区间中，并对这三个区间进行维护即可</li>
</ul>
<p><strong>nums[cur] 小于 v 的时候</strong></p>
<p>当我们遇到的 <code>nums[cur]</code> 小于 v 的时候，数据可能是这样的。</p>
<p></p>
<p>你可以发现，我们怎么才能让 <code>num[0...i)</code> 的区间扩大呢？显然我们这时候没办法扩大，一旦扩大，我们的数据就会覆盖掉 <code>nums[i...j)</code> 这个区间里面的数据，所以我们可以让 <code>nums[i...j)</code> 这个区间的第一个元素放到 <code>j</code> 所在的位置，其实就相当于移走了最开头的元素放到了 <code>nums[i...j)</code> 这个区间的尾巴上，然后为了维护 <code>nums[i...j)</code> 这个区间的定义，我们需要让 <code>j</code> 的值增加 1；好巧不巧，这个时候 <code>cur</code> 的值是等于 <code>j</code> 的值的，所以我们直接交换 <code>nums[i]</code> 和 <code>nums[j]</code> 的值就可以了，然后我们分别让 <code>i, j, cur</code> 的值分别都增加 1 即可，随后就变成了下面这样子。</p>
<p></p>
<p>思考一下，<code>j</code> 和 <code>cur</code> 是不是会一直保持着指向同一个元素呢？答案是：会的，他们两个在这个过程中会一直指向同一个元素。</p>
<p>到目前为止我们看到的是没有遇到 <code>nums[cur] &gt; v</code> 的情况，那么我们接着看。</p>
<p><strong>nums[cur] &gt; v 的时候</strong></p>
<p>如果我们碰到了当前的值 <code>nums[cur]</code> 是大于 <code>v</code> 的，那么我们只需要让 <code>nums[cur]</code> 和 <code>nums[k]</code> 的值进行交换，然后只让索引 <code>k</code> 向左移动一下就可以了； 为什么所以 <code>cur</code> 不需要移动？这是因为，<code>nums[k]</code> 这个值本来是我们没有访问过的，所以相当于经过交换后， <code>nums[cur]</code> 正是我们可以访问的下一个元素。</p>
<p>假设数据一开始是这样的：</p>
<p></p>
<p>这时候我们交换 <code>nums[cur]</code> 和 <code>nums[k]</code></p>
<p></p>
<p><strong>nums[cur] == v 的时候</strong></p>
<p>当 <code>nums[cur]</code> 和 <code>v</code> 相等的时候，我们需要把这个值放在 <code>nums[i...j)</code> 这个区间中，这也太容易了，我们只需要让 <code>j, cur</code> 向右移动一下就可以了，这里就不做图演示了。</p>
<p><strong>算法什么时候停止？</strong></p>
<p>根据我们的定义，<code>nums(k...n-1]</code> 区间代表的是大于 <code>v</code> 的那部分，由于左侧是开区间，所以 <code>nums[k]</code> 是可以被继续访问的，那么就是说，当 <code>cur &gt; k</code> 的时候算法结束，注意 <code>cur</code> 等于 <code>k</code> 的时候还是需要继续的。</p>
<p>从上述的分析过程可以发现 <code>cur</code> 的值是等于 <code>j</code> 的，所以在代码实现中我去掉了  <code>cur</code> 索引</p>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">sortColors</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token boolean">None</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token triple-quoted-string string">"""</span>
<span class="line">        Do not return anything, modify nums in-place instead.</span>
<span class="line">        """</span></span>
<span class="line">        self<span class="token punctuation">.</span>partition<span class="token punctuation">(</span>nums<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">partition</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">,</span> v<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token boolean">None</span><span class="token punctuation">:</span></span>
<span class="line">        i <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        j <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        k <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> j <span class="token operator">&lt;=</span> k<span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&lt;</span> v<span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">                j <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">elif</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> v<span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span></span>
<span class="line">                k <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">else</span><span class="token punctuation">:</span></span>
<span class="line">                j <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void sortColors(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">       partition(nums, 1);</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    void partition(vector&lt;int&gt;&amp; nums, int v) {</span>
<span class="line">        // 维护 nums[0...i) 为小于 v 的数值所在区间</span>
<span class="line">        // 维护 nums[i...j) 为等于 v 的数值所在区间</span>
<span class="line">        // 维护 nums(k...n-1] 为大于 v 的数值所在区间</span>
<span class="line"></span>
<span class="line">        int i = 0;</span>
<span class="line">        int j = 0;</span>
<span class="line">        int k = nums.size() - 1;</span>
<span class="line"></span>
<span class="line">        while( j &lt;= k ) {</span>
<span class="line">            if( nums[j] &lt; v ) {</span>
<span class="line">                // 从 nums[i...j) 区间中 为 nums[0...i) 区间让出一个位置</span>
<span class="line">                swap(nums[i++], nums[j++]);</span>
<span class="line">            } else if( nums[j] &gt; v ) {</span>
<span class="line">                // nums[cur] &gt; v</span>
<span class="line">                swap(nums[k--], nums[j]);</span>
<span class="line">            } else {</span>
<span class="line">                j++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">sortColors</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token function">partition</span><span class="token punctuation">(</span>nums<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">partition</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">,</span> <span class="token keyword">int</span> v<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> k <span class="token operator">=</span> nums<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span><span class="token punctuation">(</span> j <span class="token operator">&lt;=</span> k <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&lt;</span> v <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">int</span> temp <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> temp<span class="token punctuation">;</span></span>
<span class="line">                i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">                j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> v <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">int</span> temp <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> temp<span class="token punctuation">;</span></span>
<span class="line">                k<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">                j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">sortColors</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span>  <span class="token punctuation">{</span></span>
<span class="line">    <span class="token function">partition</span><span class="token punctuation">(</span>nums<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">partition</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> v <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    i <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line">    j <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line">    k <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> j <span class="token operator">&lt;=</span> k <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">if</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&lt;</span> v <span class="token punctuation">{</span></span>
<span class="line">            nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">            i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> v <span class="token punctuation">{</span></span>
<span class="line">            nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span></span>
<span class="line">            k<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">            j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0088 合并两个有序数组</title>
      <link>https://blueberry-universe.cn/2024-12-22-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-22-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0088 合并两个有序数组</source>
      <description>0088 合并两个有序数组
你好啊，我是蓝莓，今天是每日一题的第 6 天。
题目清单：https://blueberry-universe.cn/lc/index.html
引用力扣题目：https://leetcode.cn/problems/merge-sorted-array/
题目描述
给你两个按 非递减顺序 排列的整数数组 nums1 和 n...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 6 天。</p>
<p><strong>题目清单</strong>：https://blueberry-universe.cn/lc/index.html</p>
<p><strong>引用力扣题目</strong>：https://leetcode.cn/problems/merge-sorted-array/</p>
<h2>题目描述</h2>
<p>给你两个按 <strong>非递减顺序</strong> 排列的整数数组 <code>nums1</code> 和 <code>nums2</code>，另有两个整数 <code>m</code> 和 <code>n</code> ，分别表示 <code>nums1</code> 和 <code>nums2</code> 中的元素数目。</p>
<p>请你 <strong>合并</strong> <code>nums2</code> 到 <code>nums1</code> 中，使合并后的数组同样按 <strong>非递减顺序</strong> 排列。</p>
<p>**注意：**最终，合并后数组不应由函数返回，而是存储在数组 <code>nums1</code> 中。为了应对这种情况，<code>nums1</code> 的初始长度为 <code>m + n</code>，其中前 <code>m</code> 个元素表示应合并的元素，后 <code>n</code> 个元素为 <code>0</code> ，应忽略。<code>nums2</code> 的长度为 <code>n</code> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3</span>
<span class="line">输出：[1,2,2,3,5,6]</span>
<span class="line">解释：需要合并 [1,2,3] 和 [2,5,6] 。</span>
<span class="line">合并结果是 [1,2,2,3,5,6] ，其中斜体加粗标注的为 nums1 中的元素。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [1], m = 1, nums2 = [], n = 0</span>
<span class="line">输出：[1]</span>
<span class="line">解释：需要合并 [1] 和 [] 。</span>
<span class="line">合并结果是 [1] 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [0], m = 0, nums2 = [1], n = 1</span>
<span class="line">输出：[1]</span>
<span class="line">解释：需要合并的数组是 [] 和 [1] 。</span>
<span class="line">合并结果是 [1] 。</span>
<span class="line">注意，因为 m = 0 ，所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>nums1.length == m + n</code></li>
<li><code>nums2.length == n</code></li>
<li><code>0 &lt;= m, n &lt;= 200</code></li>
<li><code>1 &lt;= m + n &lt;= 200</code></li>
<li><code>-109 &lt;= nums1[i], nums2[j] &lt;= 109</code></li>
</ul>
<p>**进阶：**你可以设计实现一个时间复杂度为 <code>O(m + n)</code> 的算法解决此问题吗？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目是将两个有序的数组合并成一个数组，所以我们直接采用归并排序的思路即可</li>
<li>归并排序中的 <code>merge</code> 操作做了什么 ？</li>
<li>在归并排序中，通常情况下对两个有序的数组进行归并，我们分别使用 <code>i</code> 和 <code>j</code> 两个索引指向两个数组的开头元素。然后每次选择 <code>i</code> 和 <code>j</code> 索引指向的较小的元素依次放在最终的结果中。比如我们选择了 <code>i</code> 索引所指向的元素，那么我们就让 <code>i</code> 索引向右移动一个位置，继续重复刚才的过程即可。</li>
<li>需要注意的是，由于是对两个数组进行归并，非常有可能其中一个数组的元素已经遍历完了，但是另一个数组的元素还没有遍历完，所以剩下的另一个数组的元素就直接无脑的依次堆叠在最终的结果中即可。</li>
<li>因为题目要求的是我们把最后归并完成的结果放在 <code>nums1</code> 数组中，所以在代码实现的最后需要把我们的结果复制进去。</li>
<li>在执行归并的过程中，我们使用 <code>i</code> 索引遍历 <code>nums1</code> 数组；<code>i</code> 的初始值为 0，并且小于数组长度 m</li>
<li>我们使用 <code>j</code> 索引遍历 <code>nums2</code> 数组，<code>j</code> 的初始值为 0，并且小于数组长度 n</li>
<li>定义一个 <code>res</code> 数组用来存放最后的结果，它的长度为 <code>nums1</code> 的长度 加上 <code>nums2</code> 的长度，也就是 <code>m+n</code></li>
<li>使用 <code>cur</code> 索引遍历 <code>res</code> 数组，<code>res</code> 的初始值为 0</li>
<li>代码中需要注意的一个点是：在归并的时候，我们需要先判断是不是有一个数组已经遍历完了？如果都没有遍历完，我们才能比较大小，一旦有一个数组遍历完了，那么执行比较大小的操作就会越界，所以在 <code>while</code> 循环中我把比较大小的那一步放在了后面，而把判断数组遍历是否结束的步骤放在了前面。</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">merge</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums1<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">,</span> m<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">,</span> nums2<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">,</span> n<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token boolean">None</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token triple-quoted-string string">"""</span>
<span class="line">        Do not return anything, modify nums1 in-place instead.</span>
<span class="line">        """</span></span>
<span class="line">        i <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        j <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">        res <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;</span> m <span class="token keyword">or</span> j <span class="token operator">&lt;</span> n<span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> i <span class="token operator">>=</span> m<span class="token punctuation">:</span></span>
<span class="line">                <span class="token comment"># nums1 数组已经全部遍历结束 &amp;&amp; nums2 数组还没有结束</span></span>
<span class="line">                res<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">                j <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">elif</span> j <span class="token operator">>=</span> n<span class="token punctuation">:</span></span>
<span class="line">                <span class="token comment"># nums2 数组已经全部遍历结束 &amp;&amp; nums1 数组还没有结束</span></span>
<span class="line">                res<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">elif</span> nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&lt;</span> nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">:</span></span>
<span class="line">                <span class="token comment"># nums1[i] 的元素较小 选择 nums1[i]</span></span>
<span class="line">                res<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">else</span><span class="token punctuation">:</span></span>
<span class="line">                res<span class="token punctuation">.</span>append<span class="token punctuation">(</span>nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">                j <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        nums1<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span> <span class="token operator">=</span> res<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void merge(vector&lt;int&gt;&amp; nums1, int m, vector&lt;int&gt;&amp; nums2, int n) {</span>
<span class="line">        int i = 0;</span>
<span class="line">        int j = 0;</span>
<span class="line">        </span>
<span class="line">        int cur = 0;</span>
<span class="line">        vector&lt;int&gt; res(m+n, 0);</span>
<span class="line"></span>
<span class="line">        while( i &lt; m || j &lt; n ) {</span>
<span class="line">            if( i &gt;= m ) {</span>
<span class="line">                // nums1 数组已经全部遍历结束 &amp;&amp; nums2 数组还没有结束</span>
<span class="line">                res[cur++] = nums2[j++];</span>
<span class="line">            } else if( j &gt;= n ) {</span>
<span class="line">                // nums2 数组已经全部遍历结束 &amp;&amp; nums1 数组还没有结束</span>
<span class="line">                res[cur++] = nums1[i++];</span>
<span class="line">            } else if( nums1[i] &lt; nums2[j]) {</span>
<span class="line">                // nums1[i] 的元素较小 选择 nums1[i] </span>
<span class="line">                res[cur++] = nums1[i++];</span>
<span class="line">            } else {</span>
<span class="line">                // nums1[i] &gt; nums2[j]</span>
<span class="line">                res[cur++] = nums2[j++];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        cur = 0;</span>
<span class="line">        while( cur &lt; nums1.size() ) {</span>
<span class="line">            nums1[cur] = res[cur];</span>
<span class="line">            cur++;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">merge</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums1<span class="token punctuation">,</span> <span class="token keyword">int</span> m<span class="token punctuation">,</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums2<span class="token punctuation">,</span> <span class="token keyword">int</span> n<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        </span>
<span class="line">        <span class="token keyword">int</span> cur <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> res <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span>m<span class="token operator">+</span>n<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span><span class="token punctuation">(</span> i <span class="token operator">&lt;</span> m <span class="token operator">||</span> j <span class="token operator">&lt;</span> n <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> i <span class="token operator">>=</span> m <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// nums1 数组已经全部遍历结束 &amp;&amp; nums2 数组还没有结束</span></span>
<span class="line">                res<span class="token punctuation">[</span>cur<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> nums2<span class="token punctuation">[</span>j<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span> j <span class="token operator">>=</span> n <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// nums2 数组已经全部遍历结束 &amp;&amp; nums1 数组还没有结束</span></span>
<span class="line">                res<span class="token punctuation">[</span>cur<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> nums1<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span> nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&lt;</span> nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// nums1[i] 的元素较小 选择 nums1[i] </span></span>
<span class="line">                res<span class="token punctuation">[</span>cur<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> nums1<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// nums1[i] > nums2[j]</span></span>
<span class="line">                res<span class="token punctuation">[</span>cur<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> nums2<span class="token punctuation">[</span>j<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        cur <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">while</span><span class="token punctuation">(</span> cur <span class="token operator">&lt;</span> nums1<span class="token punctuation">.</span>length <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            nums1<span class="token punctuation">[</span>cur<span class="token punctuation">]</span> <span class="token operator">=</span> res<span class="token punctuation">[</span>cur<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            cur<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">merge</span><span class="token punctuation">(</span>nums1 <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> m <span class="token builtin">int</span><span class="token punctuation">,</span> nums2 <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> n <span class="token builtin">int</span><span class="token punctuation">)</span>  <span class="token punctuation">{</span></span>
<span class="line">    i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">    j <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    cur <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">    res <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> m<span class="token operator">+</span>n<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token operator">&lt;</span> m <span class="token operator">||</span> j <span class="token operator">&lt;</span> n <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">if</span> i <span class="token operator">>=</span> m  <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// nums1 数组已经全部遍历结束 &amp;&amp; nums2 数组还没有结束</span></span>
<span class="line">            res<span class="token punctuation">[</span>cur<span class="token punctuation">]</span> <span class="token operator">=</span> nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> j <span class="token operator">>=</span> n <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// nums2 数组已经全部遍历结束 &amp;&amp; nums1 数组还没有结束</span></span>
<span class="line">            res<span class="token punctuation">[</span>cur<span class="token punctuation">]</span> <span class="token operator">=</span> nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&lt;</span> nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// nums1[i] 的元素较小 选择 nums1[i] </span></span>
<span class="line">            res<span class="token punctuation">[</span>cur<span class="token punctuation">]</span> <span class="token operator">=</span> nums1<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token comment">// nums1[i] > nums2[j]</span></span>
<span class="line">            res<span class="token punctuation">[</span>cur<span class="token punctuation">]</span> <span class="token operator">=</span> nums2<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        cur<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token function">copy</span><span class="token punctuation">(</span>nums1<span class="token punctuation">,</span> res<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0215 数组中的第k个最大的元素</title>
      <link>https://blueberry-universe.cn/2024-12-23-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-23-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0215 数组中的第k个最大的元素</source>
      <description>0215 数组中的第k个最大的元素
你好啊，我是蓝莓，今天是每日一题的第 7 天。
题目清单：https://blueberry-universe.cn/lc/index.html
引用力扣题目：https://leetcode.cn/problems/kth-largest-element-in-an-array/description/
题目描述
...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 7 天。</p>
<p><strong>题目清单</strong>：https://blueberry-universe.cn/lc/index.html</p>
<p><strong>引用力扣题目</strong>：https://leetcode.cn/problems/kth-largest-element-in-an-array/description/</p>
<h2>题目描述</h2>
<p>给定整数数组 <code>nums</code> 和整数 <code>k</code>，请返回数组中第 <code>**k**</code> 个最大的元素。</p>
<p>请注意，你需要找的是数组排序后的第 <code>k</code> 个最大的元素，而不是第 <code>k</code> 个不同的元素。</p>
<p>你必须设计并实现时间复杂度为 <code>O(n)</code> 的算法解决此问题。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: [3,2,1,5,6,4], k = 2</span>
<span class="line">输出: 5</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: [3,2,3,1,2,4,5,5,6], k = 4</span>
<span class="line">输出: 4</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= k &lt;= nums.length &lt;= 105</code></li>
<li><code>-104 &lt;= nums[i] &lt;= 104</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>最简单的思路应该是将整个 <code>nums</code> 数组进行排序，然后计算出第 k 大的元素所在的位置，就可以求解出结果了</li>
<li>另一种思路，我们可以使用 <code>快速排序</code> + <code>分治</code> 的方法实现</li>
<li>回忆快速排序中 <code>partition</code> 的操作需要传入一个 <code>nums</code> 数组以及一个数值 <code>v</code> ，我们会根据 <code>v</code> 的值将所有小于它的放在左边，大于它的放在右边，等于<code>v</code> 的值放在中间。也就是说中间的这部分值是已经完成排序的，如果中间这部分的某个元素的小标刚好就是我们要找的第 k 大的元素的下标，那么算法就已经结束了</li>
<li>如果我们要找的元素的下标在中间这部分元素的右侧，那么我们只需要对右侧的部分再继续使用 <code>partition</code> 操作即可，接着只需要重复上面的过程</li>
<li>如果我们要找的元素的下标在中间这部分元素的左侧，那么我们只需要对左侧的这部分元素再继续使用 <code>partition</code> 操作即可，接着继续重复上述操作</li>
<li>如果我们一旦找到了指定元素就直接返回就可以了</li>
<li>这里的 <code>partition</code> 操作的过程可参考这篇文章 <a href="https://mp.weixin.qq.com/s/rTfC5UCxsZ7HomMGDUx6TA" target="_blank" rel="noopener noreferrer">「每日一题」力扣 75 颜色分类</a> ，我只是在 <code>partition</code> 操作返回的时候，返回了中间那部分的区间，其他的都是一模一样的抄了过来</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">findKthLargest</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">,</span> k<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">int</span><span class="token punctuation">:</span></span>
<span class="line">        l <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        r <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line">        <span class="token comment"># 第 k 大的元素所在 nums 数组中的位置 (按照从小到大的顺序摆放)</span></span>
<span class="line">        p <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token operator">-</span> k</span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> l <span class="token operator">&lt;=</span> r<span class="token punctuation">:</span></span>
<span class="line">            pivot <span class="token operator">=</span> random<span class="token punctuation">.</span>choice<span class="token punctuation">(</span>nums<span class="token punctuation">[</span>l<span class="token punctuation">:</span>r<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>  <span class="token comment"># 在 nums 中随机选取一个数值</span></span>
<span class="line">            first<span class="token punctuation">,</span> second <span class="token operator">=</span> self<span class="token punctuation">.</span>partition<span class="token punctuation">(</span>nums<span class="token punctuation">,</span> pivot<span class="token punctuation">,</span> l<span class="token punctuation">,</span> r<span class="token punctuation">)</span></span>
<span class="line">            <span class="token keyword">if</span> first <span class="token operator">&lt;=</span> p <span class="token keyword">and</span> second <span class="token operator">>=</span> p<span class="token punctuation">:</span></span>
<span class="line">                <span class="token comment"># 如果 p 落在 interval 表示的中间部分的区间里</span></span>
<span class="line">                <span class="token comment"># 说明第 k 大的元素已经被放在了正确的位置</span></span>
<span class="line">                <span class="token keyword">return</span> nums<span class="token punctuation">[</span>p<span class="token punctuation">]</span></span>
<span class="line">            <span class="token keyword">elif</span> first <span class="token operator">></span> p<span class="token punctuation">:</span></span>
<span class="line">                <span class="token comment"># 说明应该在左边继续寻找</span></span>
<span class="line">                r <span class="token operator">=</span> first <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">else</span><span class="token punctuation">:</span></span>
<span class="line">                <span class="token comment"># interval.second &lt; p</span></span>
<span class="line">                <span class="token comment"># 说明应该在右边继续寻找</span></span>
<span class="line">                l <span class="token operator">=</span> second <span class="token operator">+</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">partition</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> nums<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">,</span> v<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">,</span> l<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">,</span> r<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> Tuple<span class="token punctuation">:</span></span>
<span class="line">        i <span class="token operator">=</span> l</span>
<span class="line">        j <span class="token operator">=</span> l</span>
<span class="line">        k <span class="token operator">=</span> r</span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> j <span class="token operator">&lt;=</span> k<span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&lt;</span> v<span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">                j <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">elif</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> v<span class="token punctuation">:</span></span>
<span class="line">                nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span></span>
<span class="line">                k <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">else</span><span class="token punctuation">:</span></span>
<span class="line">                j <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token comment"># 返回区别 nums[i, j-1] 代表等于数值 v 的区间</span></span>
<span class="line">        <span class="token keyword">return</span> i<span class="token punctuation">,</span> j<span class="token operator">-</span><span class="token number">1</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int findKthLargest(vector&lt;int&gt;&amp; nums, int k) {</span>
<span class="line">        int l = 0;</span>
<span class="line">        int r = nums.size() - 1;</span>
<span class="line">        // 第 k 大的元素所在 nums 数组中的位置 (按照从小到大的顺序摆放)</span>
<span class="line">        int p = nums.size() - k;</span>
<span class="line"></span>
<span class="line">        srand(time(nullptr)); // 使用当前时间初始化随机种子</span>
<span class="line"></span>
<span class="line">        while( l &lt;= r ) {</span>
<span class="line">            int select = l + rand() % (r - l + 1); // 生成 [l, r] 的随机整数</span>
<span class="line">            pair&lt;int, int&gt; interval = partition(nums, nums[select], l, r);</span>
<span class="line">            if( interval.first &lt;= p &amp;&amp; interval.second &gt;= p ) {</span>
<span class="line">                // 如果 p 落在 interval 表示的中间部分的区间里</span>
<span class="line">                // 说明第 k 大的元素已经被放在了正确的位置</span>
<span class="line">                return nums[p];</span>
<span class="line">            } else if( interval.first &gt; p ) {</span>
<span class="line">                // 说明应该在左边继续寻找</span>
<span class="line">                r = interval.first - 1;</span>
<span class="line">            } else {</span>
<span class="line">                // interval.second &lt; p</span>
<span class="line">                // 说明应该在右边继续寻找</span>
<span class="line">                l = interval.second + 1;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return -1;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    pair&lt;int, int&gt; partition(vector&lt;int&gt;&amp; nums, int v, int l, int r) {</span>
<span class="line">        // 维护 nums[l...i) 为小于 v 的数值所在区间</span>
<span class="line">        // 维护 nums[l...j) 为等于 v 的数值所在区间</span>
<span class="line">        // 维护 nums(k...r] 为大于 v 的数值所在区间</span>
<span class="line"></span>
<span class="line">        int i = l;</span>
<span class="line">        int j = l;</span>
<span class="line">        int k = r;</span>
<span class="line"></span>
<span class="line">        while( j &lt;= k ) {</span>
<span class="line">            if( nums[j] &lt; v ) {</span>
<span class="line">                // 从 nums[i...j) 区间中 为 nums[0...i) 区间让出一个位置</span>
<span class="line">                swap(nums[i++], nums[j++]);</span>
<span class="line">            } else if( nums[j] &gt; v ) {</span>
<span class="line">                // nums[cur] &gt; v</span>
<span class="line">                swap(nums[k--], nums[j]);</span>
<span class="line">            } else {</span>
<span class="line">                j++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 返回区别 nums[i, j-1] 代表等于数值 v 的区间</span>
<span class="line">        return make_pair(i, j-1);</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">findKthLargest</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">,</span> <span class="token keyword">int</span> k<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> l <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> r <span class="token operator">=</span> nums<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token comment">// 第 k 大的元素所在 nums 数组中的位置 (按照从小到大的顺序摆放)</span></span>
<span class="line">        <span class="token keyword">int</span> p <span class="token operator">=</span> nums<span class="token punctuation">.</span>length <span class="token operator">-</span> k<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token class-name">Random</span> random <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span><span class="token punctuation">(</span> l <span class="token operator">&lt;=</span> r <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">int</span> select <span class="token operator">=</span> random<span class="token punctuation">.</span><span class="token function">nextInt</span><span class="token punctuation">(</span>r <span class="token operator">-</span> l <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> l<span class="token punctuation">;</span> <span class="token comment">// 生成 [l, r] 的随机整数</span></span>
<span class="line">            <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> interval <span class="token operator">=</span> <span class="token function">partition</span><span class="token punctuation">(</span>nums<span class="token punctuation">,</span> nums<span class="token punctuation">[</span>select<span class="token punctuation">]</span><span class="token punctuation">,</span> l<span class="token punctuation">,</span> r<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> interval<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">&lt;=</span> p <span class="token operator">&amp;&amp;</span> interval<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">>=</span> p <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// 如果 p 落在 interval 表示的中间部分的区间里</span></span>
<span class="line">                <span class="token comment">// 说明第 k 大的元素已经被放在了正确的位置</span></span>
<span class="line">                <span class="token keyword">return</span> nums<span class="token punctuation">[</span>p<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span> interval<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">></span> p <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// 说明应该在左边继续寻找</span></span>
<span class="line">                r <span class="token operator">=</span> interval<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// interval[1] &lt; p</span></span>
<span class="line">                <span class="token comment">// 说明应该在右边继续寻找</span></span>
<span class="line">                l <span class="token operator">=</span> interval<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">     <span class="token keyword">public</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">partition</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">,</span> <span class="token keyword">int</span> v<span class="token punctuation">,</span> <span class="token keyword">int</span> l<span class="token punctuation">,</span> <span class="token keyword">int</span> r<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> l<span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> j <span class="token operator">=</span> l<span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> k <span class="token operator">=</span> r<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span><span class="token punctuation">(</span> j <span class="token operator">&lt;=</span> k <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&lt;</span> v <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">int</span> temp <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> temp<span class="token punctuation">;</span></span>
<span class="line">                i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">                j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> v <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">int</span> temp <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">                nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> temp<span class="token punctuation">;</span></span>
<span class="line">                k<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">                j<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">         </span>
<span class="line">		<span class="token comment">// 返回区别 nums[i, j-1] 代表等于数值 v 的区间</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span>i<span class="token punctuation">,</span> j<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">findKthLargest</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> k <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	l <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line">	r <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line">	<span class="token comment">// 第 k 大的元素所在 nums 数组中的位置 (按照从小到大的顺序摆放)</span></span>
<span class="line">	p <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span> <span class="token operator">-</span> k</span>
<span class="line"></span>
<span class="line">	rand<span class="token punctuation">.</span><span class="token function">Seed</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span><span class="token function">Now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">UnixNano</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 使用当前时间初始化随机种子</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> l <span class="token operator">&lt;=</span> r <span class="token punctuation">{</span></span>
<span class="line">		selectIndex <span class="token operator">:=</span> rand<span class="token punctuation">.</span><span class="token function">Intn</span><span class="token punctuation">(</span>r<span class="token operator">-</span>l<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> l <span class="token comment">// 生成 [l, r] 的随机整数</span></span>
<span class="line">		first<span class="token punctuation">,</span> second <span class="token operator">:=</span> <span class="token function">partition</span><span class="token punctuation">(</span>nums<span class="token punctuation">,</span> nums<span class="token punctuation">[</span>selectIndex<span class="token punctuation">]</span><span class="token punctuation">,</span> l<span class="token punctuation">,</span> r<span class="token punctuation">)</span></span>
<span class="line">		<span class="token keyword">if</span> first <span class="token operator">&lt;=</span> p <span class="token operator">&amp;&amp;</span> second <span class="token operator">>=</span> p <span class="token punctuation">{</span></span>
<span class="line">			<span class="token comment">// 如果 p 落在 [first, second] 区间内</span></span>
<span class="line">			<span class="token comment">// 说明第 k 大的元素已经被放在了正确的位置</span></span>
<span class="line">			<span class="token keyword">return</span> nums<span class="token punctuation">[</span>p<span class="token punctuation">]</span></span>
<span class="line">		<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> first <span class="token operator">></span> p <span class="token punctuation">{</span></span>
<span class="line">			<span class="token comment">// 说明应该在左边继续寻找</span></span>
<span class="line">			r <span class="token operator">=</span> first <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line">		<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">			<span class="token comment">// second &lt; p</span></span>
<span class="line">			<span class="token comment">// 说明应该在右边继续寻找</span></span>
<span class="line">			l <span class="token operator">=</span> second <span class="token operator">+</span> <span class="token number">1</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// partition 函数，将 nums[l:r] 数组划分为小于、等于和大于基准值的部分</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">partition</span><span class="token punctuation">(</span>nums <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> v<span class="token punctuation">,</span> l<span class="token punctuation">,</span> r <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	i <span class="token operator">:=</span> l</span>
<span class="line">	j <span class="token operator">:=</span> l</span>
<span class="line">	k <span class="token operator">:=</span> r</span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> j <span class="token operator">&lt;=</span> k <span class="token punctuation">{</span></span>
<span class="line">		<span class="token keyword">if</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&lt;</span> v <span class="token punctuation">{</span></span>
<span class="line">			nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">			i<span class="token operator">++</span></span>
<span class="line">			j<span class="token operator">++</span></span>
<span class="line">		<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> v <span class="token punctuation">{</span></span>
<span class="line">			nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">,</span> nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span></span>
<span class="line">			k<span class="token operator">--</span></span>
<span class="line">		<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">			j<span class="token operator">++</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 返回 [i, j-1]，即等于数值 v 的区间</span></span>
<span class="line">	<span class="token keyword">return</span> i<span class="token punctuation">,</span> j <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0167 两数之和 II - 输入有序数组</title>
      <link>https://blueberry-universe.cn/2024-12-24-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-24-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0167 两数之和 II - 输入有序数组</source>
      <description>0167 两数之和 II - 输入有序数组
你好啊，我是蓝莓，今天是每日一题的第 8 天。
题目清单非常重要，每个题目都是经过分类的，可以有针对性的使用这些题目进行练习，可以看看。
题目清单：点我
引用力扣题目：点我
题目描述
给你一个下标从 1 开始的整数数组 numbers ，该数组已按 非递减顺序排列 ，请你从数组中找出满足相加之和等于目标数 t...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 8 天。</p>
<p>题目清单非常重要，每个题目都是经过分类的，可以有针对性的使用这些题目进行练习，可以看看。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">点我</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/description/" target="_blank" rel="noopener noreferrer">点我</a></p>
<h2>题目描述</h2>
<p>给你一个下标从 <strong>1</strong> 开始的整数数组 <code>numbers</code> ，该数组已按 <strong>非递减顺序排列</strong> ，请你从数组中找出满足相加之和等于目标数 <code>target</code> 的两个数。如果设这两个数分别是 <code>numbers[index1]</code> 和 <code>numbers[index2]</code> ，则 <code>1 &lt;= index1 &lt; index2 &lt;= numbers.length</code> 。</p>
<p>以长度为 2 的整数数组 <code>[index1, index2]</code> 的形式返回这两个整数的下标 <code>index1</code> 和 <code>index2</code>。</p>
<p>你可以假设每个输入 <strong>只对应唯一的答案</strong> ，而且你 <strong>不可以</strong> 重复使用相同的元素。</p>
<p>你所设计的解决方案必须只使用常量级的额外空间。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：numbers = [2,7,11,15], target = 9</span>
<span class="line">输出：[1,2]</span>
<span class="line">解释：2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：numbers = [2,3,4], target = 6</span>
<span class="line">输出：[1,3]</span>
<span class="line">解释：2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：numbers = [-1,0], target = -1</span>
<span class="line">输出：[1,2]</span>
<span class="line">解释：-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>2 &lt;= numbers.length &lt;= 3 * 104</code></li>
<li><code>-1000 &lt;= numbers[i] &lt;= 1000</code></li>
<li><code>numbers</code> 按 <strong>非递减顺序</strong> 排列</li>
<li><code>-1000 &lt;= target &lt;= 1000</code></li>
<li><strong>仅存在一个有效答案</strong></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目开始会有四个使用双指针的题目</li>
<li>对于这个题目来说，最容易想到的暴力解法就是使用两层循环，遍历所有的两个数值为一对的组合</li>
<li>对于组合来说相信并不陌生，最简单的代码实现可能是下面这样子的</li>
</ul>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 寻找组合的两层循环</span>
<span class="line"></span>
<span class="line">for( int i = 0 ; i &lt; len(numbers) ; i++ ) {</span>
<span class="line">    for( int j = i+1 ; j &lt; len(numbers) ; j++ ) {</span>
<span class="line">        // 在这里写对于每一对的要进行判断的逻辑</span>
<span class="line">        // 你可以在这里判断 numbers[i] 和 numbers[j] 相加后的结果是否满足 target</span>
<span class="line">        // 并做一些必要的处理</span>
<span class="line">    }</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>你可以很容易的发现，这里的 <code>i</code> 是永远小于 <code>j</code> 的，这样可以保证我们不会寻找出重复的组合</li>
<li>对于经典的两层循环的代码可能是下面这样的</li>
</ul>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 经典的两层循环</span>
<span class="line">for( int i = 0 ; i &lt; len(numbers) ; i++ ) {</span>
<span class="line">	for( int j = 0 ; j &lt; len(numbers) ; j++ ) {</span>
<span class="line">		// 在这里写对于每一对的要进行判断的逻辑</span>
<span class="line">        // 你可以在这里判断 numbers[i] 和 numbers[j] 相加后的结果是否满足 target</span>
<span class="line">        // 并做一些必要的处理</span>
<span class="line">	}</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li><code>经典的两层循环</code> 和 <code>寻找组合的两层循环</code> 有什么区别 ？ 区别就在于 <code>经典的两层循环</code> 会寻找出重复的情况，比如对于一对组合 <code>numbers[5]</code> 和 <code>numbers[10]</code> ，我们可以让 <code>i</code> 和 <code>j</code> 分别等于 <code>5</code> 和 <code>10</code> 这就会出现重复的情况了。所以防止不出现重复的情况，我们应该使用 <code>寻找组合的两层循环</code> 这种写法，这种写法既不会出现 <code>i</code> 等于 <code>j</code> 的情况，也不会出现重复的情况</li>
<li>虽然说我们使用了 <code>寻找组合的两层循环</code> 可以降低很多不必要的操作，但是它依然是 O(N^2) 的时间复杂度</li>
<li>对于这个题目，我们要设计一个在 O(N) 的时间复杂度就可以完成的算法。双指针是什么 ？</li>
<li>我们设置索引 <code>i</code> 并设置初始值为 <code>0</code></li>
<li>我们设置索引 <code>j</code> 并设置初始值为 <code>len(numbers) - 1</code> 也就是让 <code>j</code> 指向数组中的最后一个元素</li>
<li>我们检查 <code>numbers[i] + numbers[j]</code> 的值是不是等于 <code>target</code> 的值，如果相等的话，就说明我们找到了，如果不相等的话，只有可能出现两种情况。</li>
<li>第一种情况：<code>numbers[i] + numbers[j]</code> 的值大于 <code>target</code>，这种情况下可以选择让 <code>j</code> 的索引向左移动一下。因为数组是从小到大排序的，所以让 <code>j</code> 向左移动可以减小 <code>numbers[i] + numbers[j]</code>  的值。为什么我们不让 <code>i</code> 向右移动？因为如果让 <code>i</code> 向右移动势必会让  <code>numbers[i] + numbers[j]</code>  的值增大。也就是说：我们可以排除掉所有固定 <code>j</code> 的情况下， <code>i &lt; j</code> 的情况下 <code>numbers[i] + numbers[j]</code> 的值了。通过这种方法，我们进一步缩小了搜索的空间。</li>
<li>第二种情况：<code>numbers[i] + numbers[j] </code> 的值小于 <code>target</code>，这种情况下可以选择让 <code>i</code> 的索引向右移动一下。这样，<code>numbers[i] + numbers[j] </code>  就会增大一些。同理，我们思考一下，为什么这种情况下不能让 <code>j</code> 来向左移动？因为在固定 <code>i</code> 的情况下，所有 <code>j &gt; i</code> 情况下的 <code>numbers[i] + numbers[j]</code> 的值都只会比当前的值更小。</li>
<li>相比于使用 <code>寻找组合的两层循环</code> 来说，在数组有序的情况下使用双指针可以让我们进一步的减小搜索空间。</li>
<li>在力扣上有一个题解很不错，使用了图解的方式对：为什么双指针不会漏掉一些情况的问题 ，进行了讲解。</li>
<li>题解链接：<a href="https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/solutions/87919/yi-zhang-tu-gao-su-ni-on-de-shuang-zhi-zhen-jie-fa/" target="_blank" rel="noopener noreferrer">点我</a></li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">twoSum</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> numbers<span class="token punctuation">:</span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">,</span> target<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> List<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">:</span></span>
<span class="line">        i <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">        j <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>numbers<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;</span> j<span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> numbers<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> numbers<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">==</span> target<span class="token punctuation">:</span></span>
<span class="line">                <span class="token keyword">return</span> i<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">,</span> j<span class="token operator">+</span><span class="token number">1</span></span>
<span class="line">            <span class="token keyword">elif</span> numbers<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> numbers<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> target<span class="token punctuation">:</span></span>
<span class="line">                j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">else</span><span class="token punctuation">:</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; twoSum(vector&lt;int&gt;&amp; numbers, int target) {</span>
<span class="line">        int i = 0;</span>
<span class="line">        int j = numbers.size() - 1;</span>
<span class="line"></span>
<span class="line">        while( i &lt; j ) {</span>
<span class="line">            if( numbers[i] + numbers[j] == target ) {</span>
<span class="line">                return vector({i+1, j+1});</span>
<span class="line">            } else if( numbers[i] + numbers[j] &gt; target ) {</span>
<span class="line">                j--;</span>
<span class="line">            } else {</span>
<span class="line">                // numbers[i] + numbers[j] &lt; target</span>
<span class="line">                i++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return vector({0, 0});</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">twoSum</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> numbers<span class="token punctuation">,</span> <span class="token keyword">int</span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> j <span class="token operator">=</span> numbers<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span><span class="token punctuation">(</span> i <span class="token operator">&lt;</span> j <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span><span class="token punctuation">(</span> numbers<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> numbers<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">==</span> target <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span>i<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">,</span> j<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span>  <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span> numbers<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> numbers<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> target <span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                j <span class="token operator">-=</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token comment">// numbers[i] + numbers[j] &lt; target </span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">twoSum</span><span class="token punctuation">(</span>numbers <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> target <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">    i <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line">    j <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>numbers<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token operator">&lt;</span> j <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">if</span> numbers<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> numbers<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">==</span> target <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span>i<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">,</span> j<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> numbers<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> numbers<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">></span> target <span class="token punctuation">{</span></span>
<span class="line">            j<span class="token operator">--</span></span>
<span class="line">        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">            i<span class="token operator">++</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0125 验证回文串</title>
      <link>https://blueberry-universe.cn/2024-12-25-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-25-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0125 验证回文串</source>
      <description>0125 验证回文串
你好啊，我是蓝莓，今天是每日一题的第 9 天。
题目清单：https://blueberry-universe.cn/lc/index.html
引用力扣题目：https://leetcode.cn/problems/valid-palindrome/description/
题目描述
如果在将所有大写字符转换为小写字符、并移除所...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 9 天。</p>
<p><strong>题目清单</strong>：https://blueberry-universe.cn/lc/index.html</p>
<p><strong>引用力扣题目</strong>：https://leetcode.cn/problems/valid-palindrome/description/</p>
<h2>题目描述</h2>
<p>如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后，短语正着读和反着读都一样。则可以认为该短语是一个 <strong>回文串</strong> 。</p>
<p>字母和数字都属于字母数字字符。</p>
<p>给你一个字符串 <code>s</code>，如果它是 <strong>回文串</strong> ，返回 <code>true</code> ；否则，返回 <code>false</code> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "A man, a plan, a canal: Panama"</span>
<span class="line">输出：true</span>
<span class="line">解释："amanaplanacanalpanama" 是回文串。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = "race a car"</span>
<span class="line">输出：false</span>
<span class="line">解释："raceacar" 不是回文串。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = " "</span>
<span class="line">输出：true</span>
<span class="line">解释：在移除非字母数字字符之后，s 是一个空字符串 "" 。</span>
<span class="line">由于空字符串正着反着读都一样，所以是回文串。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 2 * 105</code></li>
<li><code>s</code> 仅由可打印的 ASCII 字符组成</li>
</ul>
<h2>实现</h2>
<ul>
<li>
<p>这个题目是使用双指针的方法来实现，类似的还有这篇文章 <a href="https://mp.weixin.qq.com/s/iVi7FMz_zsnpK95uaLUiAA" target="_blank" rel="noopener noreferrer">「每日一题」力扣 167 两数之和 II - 输入有序数组</a></p>
</li>
<li>
<p>使用索引 <code>i</code> 从字符串的左侧开始遍历，使用索引 <code>j</code> 从字符串的右侧开始遍历</p>
</li>
<li>
<p>将<code>s[i]</code> 和 <code>s[j]</code>先转换为小写字母后，判断是不是相等，如果不相等的话说明不满足，返回 <code>false</code> 即可</p>
</li>
<li>
<p>但是在移动索引 <code>i</code> 和 <code>j</code> 的过程中要记得每次做完是否相等的判断后，还需要跳过那些不满足大小写字母和数字的字符；为了判断当前字符是是大小写字母或者数字，我做了一个函数 <code>isValidChar</code> 来判断</p>
</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">isValidChar</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> c<span class="token punctuation">:</span> <span class="token builtin">str</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token string">'A'</span> <span class="token operator">&lt;=</span> c <span class="token operator">&lt;=</span> <span class="token string">'Z'</span><span class="token punctuation">)</span> <span class="token keyword">or</span> <span class="token punctuation">(</span><span class="token string">'a'</span> <span class="token operator">&lt;=</span> c <span class="token operator">&lt;=</span> <span class="token string">'z'</span><span class="token punctuation">)</span> <span class="token keyword">or</span> <span class="token punctuation">(</span><span class="token string">'0'</span> <span class="token operator">&lt;=</span> c <span class="token operator">&lt;=</span> <span class="token string">'9'</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">isPalindrome</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> s<span class="token punctuation">:</span> <span class="token builtin">str</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">:</span></span>
<span class="line">        i<span class="token punctuation">,</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token builtin">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;=</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>isValidChar<span class="token punctuation">(</span>s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;=</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>isValidChar<span class="token punctuation">(</span>s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;=</span> j<span class="token punctuation">:</span></span>
<span class="line">            <span class="token keyword">if</span> s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>lower<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">.</span>lower<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">                <span class="token keyword">return</span> <span class="token boolean">False</span></span>
<span class="line">            i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">while</span> i <span class="token operator">&lt;=</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>isValidChar<span class="token punctuation">(</span>s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">while</span> i <span class="token operator">&lt;=</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>isValidChar<span class="token punctuation">(</span>s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">                j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token boolean">True</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isValidChar(char c) {</span>
<span class="line">        if( (c &gt;= 'A' &amp;&amp; c &lt;= 'Z') || (c &gt;= 'a' &amp;&amp; c &lt;= 'z') || ( c &gt;= '0' &amp;&amp; c &lt;= '9') ) {</span>
<span class="line">            return true;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return false;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    bool isPalindrome(string s) {</span>
<span class="line">        int i = 0;</span>
<span class="line">        int j = s.size() - 1;</span>
<span class="line">        </span>
<span class="line">        while( i &lt;= j &amp;&amp; !isValidChar(s[i]) ) i++;</span>
<span class="line">        while( i &lt;= j &amp;&amp; !isValidChar(s[j]) ) j--;</span>
<span class="line"></span>
<span class="line">        while( i &lt;= j ) {</span>
<span class="line">            if( tolower(s[i]) != tolower(s[j]) ) return false;</span>
<span class="line"></span>
<span class="line">            i++;</span>
<span class="line">            j--;</span>
<span class="line"></span>
<span class="line">            while( i &lt;= j &amp;&amp; !isValidChar(s[i]) ) i++;</span>
<span class="line">            while( i &lt;= j &amp;&amp; !isValidChar(s[j]) ) j--;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return true;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码实现</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">private</span> <span class="token keyword">boolean</span> <span class="token function">isValidChar</span><span class="token punctuation">(</span><span class="token keyword">char</span> c<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">(</span>c <span class="token operator">>=</span> <span class="token char">'A'</span> <span class="token operator">&amp;&amp;</span> c <span class="token operator">&lt;=</span> <span class="token char">'Z'</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">(</span>c <span class="token operator">>=</span> <span class="token char">'a'</span> <span class="token operator">&amp;&amp;</span> c <span class="token operator">&lt;=</span> <span class="token char">'z'</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token punctuation">(</span>c <span class="token operator">>=</span> <span class="token char">'0'</span> <span class="token operator">&amp;&amp;</span> c <span class="token operator">&lt;=</span> <span class="token char">'9'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">isPalindrome</span><span class="token punctuation">(</span><span class="token class-name">String</span> s<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> j <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;=</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isValidChar</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;=</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isValidChar</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            j<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;=</span> j<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Character</span><span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token class-name">Character</span><span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">            i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            j<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;=</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isValidChar</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">            <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;=</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isValidChar</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">charAt</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                j<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">isValidChar</span><span class="token punctuation">(</span>c <span class="token builtin">rune</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> unicode<span class="token punctuation">.</span><span class="token function">IsLetter</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token operator">||</span> unicode<span class="token punctuation">.</span><span class="token function">IsDigit</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">isPalindrome</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span></span>
<span class="line">    i<span class="token punctuation">,</span> j <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token operator">&lt;=</span> j <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">for</span> i <span class="token operator">&lt;=</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isValidChar</span><span class="token punctuation">(</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            i<span class="token operator">++</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">        <span class="token keyword">for</span> i <span class="token operator">&lt;=</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isValidChar</span><span class="token punctuation">(</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            j<span class="token operator">--</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">        <span class="token keyword">if</span> i <span class="token operator">&lt;=</span> j <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">if</span> unicode<span class="token punctuation">.</span><span class="token function">ToLower</span><span class="token punctuation">(</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> unicode<span class="token punctuation">.</span><span class="token function">ToLower</span><span class="token punctuation">(</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">                <span class="token keyword">return</span> <span class="token boolean">false</span></span>
<span class="line">            <span class="token punctuation">}</span></span>
<span class="line">            i<span class="token operator">++</span></span>
<span class="line">            j<span class="token operator">--</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token boolean">true</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0345 反转字符串中的元音字母</title>
      <link>https://blueberry-universe.cn/2024-12-26-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-26-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0345 反转字符串中的元音字母</source>
      <description>0345 反转字符串中的元音字母
你好啊，我是蓝莓，今天是每日一题的第 10 天。
从明天开始，题解的文章就只在我的博客更新啦，暂时不会把每个题目的题解都更新在公众号了。
如果你对刷力扣的题目感兴趣，欢迎你添加我的微信，我拉你进群一起刷题。添加微信的方法是在我的微信公众号下方点击 联系我 可以收到我的微信二维码。
题目清单就是我的博客对应的力扣题目的地...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 10 天。</p>
<p>从明天开始，题解的文章就只在我的博客更新啦，暂时不会把每个题目的题解都更新在公众号了。</p>
<p>如果你对刷力扣的题目感兴趣，<strong>欢迎你添加我的微信，我拉你进群一起刷题</strong>。添加微信的方法是在我的微信公众号下方点击 <strong>联系我</strong> 可以收到我的微信二维码。</p>
<p>题目清单就是我的博客对应的力扣题目的地址啦。</p>
<p><strong>题目清单</strong>：https://blueberry-universe.cn/lc/index.html</p>
<p><strong>引用力扣题目</strong>：https://leetcode.cn/problems/reverse-vowels-of-a-string/description/</p>
<h2>题目描述</h2>
<p>给你一个字符串 <code>s</code> ，仅反转字符串中的所有元音字母，并返回结果字符串。</p>
<p>元音字母包括 <code>'a'</code>、<code>'e'</code>、<code>'i'</code>、<code>'o'</code>、<code>'u'</code>，且可能以大小写两种形式出现不止一次。</p>
<p><strong>示例 1：</strong></p>
<p>**输入：**s = &quot;IceCreAm&quot;</p>
<p><strong>输出：</strong>&quot;AceCreIm&quot;</p>
<p><strong>解释：</strong></p>
<p><code>s</code> 中的元音是 <code>['I', 'e', 'e', 'A']</code>。反转这些元音，<code>s</code> 变为 <code>&quot;AceCreIm&quot;</code>.</p>
<p><strong>示例 2：</strong></p>
<p>**输入：**s = &quot;leetcode&quot;</p>
<p><strong>输出：</strong>&quot;leotcede&quot;</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 3 * 105</code></li>
<li><code>s</code> 由 <strong>可打印的 ASCII</strong> 字符组成</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目仍然是使用双指针，同样使用双指针的题目还有以下两篇文章</li>
</ul>
<p><a href="https://mp.weixin.qq.com/s/iVi7FMz_zsnpK95uaLUiAA" target="_blank" rel="noopener noreferrer"><strong>「每日一题」力扣 167 两数之和 II - 输入有序数组</strong></a></p>
<p><a href="https://mp.weixin.qq.com/s/qkX1T4AqnCmYhTCxtYuY9Q" target="_blank" rel="noopener noreferrer"><strong>「每日一题」力扣 125 验证回文串</strong></a></p>
<ul>
<li>使用索引 <code>i</code> 从左侧开始遍历，它的初始值为 <code>0</code></li>
<li>使用索引 <code>j</code> 从右侧开始遍历，它的初始值为 <code>n-1</code>；这里的 n 代表字符串的长度</li>
<li>交换 <code>i</code> 和 <code>j</code> 所指向的元音字母的位置，然后再让两个索引继续跳转到下一个原因字母即可</li>
<li>使用 <code>isVowelLetter</code> 函数来判断当前字符是否是元音字母</li>
</ul>
<p><strong>Python 代码实现</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">reverseVowels</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> s<span class="token punctuation">:</span> <span class="token builtin">str</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">str</span><span class="token punctuation">:</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">def</span> <span class="token function">is_vowel_letter</span><span class="token punctuation">(</span>letter<span class="token punctuation">:</span> <span class="token builtin">str</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">bool</span><span class="token punctuation">:</span></span>
<span class="line">            letter <span class="token operator">=</span> letter<span class="token punctuation">.</span>lower<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token keyword">return</span> letter <span class="token keyword">in</span> <span class="token punctuation">{</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'e'</span><span class="token punctuation">,</span> <span class="token string">'i'</span><span class="token punctuation">,</span> <span class="token string">'o'</span><span class="token punctuation">,</span> <span class="token string">'u'</span><span class="token punctuation">}</span></span>
<span class="line">        </span>
<span class="line">        s <span class="token operator">=</span> <span class="token builtin">list</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span></span>
<span class="line">        i<span class="token punctuation">,</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token builtin">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> is_vowel_letter<span class="token punctuation">(</span>s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> is_vowel_letter<span class="token punctuation">(</span>s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">            j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line">        </span>
<span class="line">        <span class="token keyword">while</span> i <span class="token operator">&lt;</span> j<span class="token punctuation">:</span></span>
<span class="line">            s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> s<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> s<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
<span class="line">            i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line">            </span>
<span class="line">            <span class="token keyword">while</span> i <span class="token operator">&lt;</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> is_vowel_letter<span class="token punctuation">(</span>s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">                i <span class="token operator">+=</span> <span class="token number">1</span></span>
<span class="line">            <span class="token keyword">while</span> i <span class="token operator">&lt;</span> j <span class="token keyword">and</span> <span class="token keyword">not</span> is_vowel_letter<span class="token punctuation">(</span>s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">                j <span class="token operator">-=</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token string">''</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>s<span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isVowelLetter(char letter) {</span>
<span class="line">        letter = tolower(letter);</span>
<span class="line">        return letter == 'a' || letter == 'e' || letter == 'i' || letter == 'o' || letter == 'u';</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    string reverseVowels(string s) {</span>
<span class="line">        int i = 0;</span>
<span class="line">        int j = s.size() - 1;</span>
<span class="line"></span>
<span class="line">        while( i &lt; j &amp;&amp; !isVowelLetter(s[i]) ) i++;</span>
<span class="line">        while( i &lt; j &amp;&amp; !isVowelLetter(s[j]) ) j--;</span>
<span class="line"></span>
<span class="line">        while( i &lt; j ) {</span>
<span class="line">            swap(s[i], s[j]);</span>
<span class="line"></span>
<span class="line">            i++;</span>
<span class="line">            j--;</span>
<span class="line"></span>
<span class="line">            while( i &lt; j &amp;&amp; !isVowelLetter(s[i]) ) i++;</span>
<span class="line">            while( i &lt; j &amp;&amp; !isVowelLetter(s[j]) ) j--;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return s;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Java 代码</strong></p>
<div class="language-java line-numbers-mode" data-highlighter="prismjs" data-ext="java"><pre><code class="language-java"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">private</span> <span class="token keyword">boolean</span> <span class="token function">isVowel</span><span class="token punctuation">(</span><span class="token keyword">char</span> letter<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        letter <span class="token operator">=</span> <span class="token class-name">Character</span><span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span>letter<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">return</span> letter <span class="token operator">==</span> <span class="token char">'a'</span> <span class="token operator">||</span> letter <span class="token operator">==</span> <span class="token char">'e'</span> <span class="token operator">||</span> letter <span class="token operator">==</span> <span class="token char">'i'</span> <span class="token operator">||</span> letter <span class="token operator">==</span> <span class="token char">'o'</span> <span class="token operator">||</span> letter <span class="token operator">==</span> <span class="token char">'u'</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">reverseVowels</span><span class="token punctuation">(</span><span class="token class-name">String</span> s<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">char</span><span class="token punctuation">[</span><span class="token punctuation">]</span> chars <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">toCharArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> j <span class="token operator">=</span> chars<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isVowel</span><span class="token punctuation">(</span>chars<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isVowel</span><span class="token punctuation">(</span>chars<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> j<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">char</span> temp <span class="token operator">=</span> chars<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            chars<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> chars<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">            chars<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> temp<span class="token punctuation">;</span></span>
<span class="line">            i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            j<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">            <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isVowel</span><span class="token punctuation">(</span>chars<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> i<span class="token operator">++</span><span class="token punctuation">;</span></span>
<span class="line">            <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> j <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token function">isVowel</span><span class="token punctuation">(</span>chars<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> j<span class="token operator">--</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>chars<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Golang 代码实现</strong></p>
<div class="language-golang line-numbers-mode" data-highlighter="prismjs" data-ext="golang"><pre><code class="language-golang"><span class="line">func isVowelLetter(c byte) bool {</span>
<span class="line">	c = byte(unicode.ToLower(rune(c)))</span>
<span class="line">	return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line">func reverseVowels(s string) string {</span>
<span class="line">	bytes := []byte(s)</span>
<span class="line">	i, j := 0, len(bytes)-1</span>
<span class="line"></span>
<span class="line">    for i &lt; j &amp;&amp; !isVowelLetter(bytes[i]) {</span>
<span class="line">        i++</span>
<span class="line">    }</span>
<span class="line">    </span>
<span class="line">    for i &lt; j &amp;&amp; !isVowelLetter(bytes[j]) {</span>
<span class="line">        j--</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">	for i &lt; j {</span>
<span class="line">        bytes[i], bytes[j] = bytes[j], bytes[i]</span>
<span class="line">			i++</span>
<span class="line">			j--</span>
<span class="line"></span>
<span class="line">	}</span>
<span class="line"></span>
<span class="line">	return string(bytes)</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0011 盛最多水的容器</title>
      <link>https://blueberry-universe.cn/2024-12-27-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-27-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0011 盛最多水的容器</source>
      <description>0011 盛最多水的容器
你好啊，我是蓝莓，今天是每日一题的第 11 天。
题目清单：一起刷力扣
引用力扣题目：力扣 11 盛最多水的容器
题目描述
给定一个长度为 n 的整数数组 height 。有 n 条垂线，第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线，使得它们与 x 轴共同构成的容器可以容纳最多...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 11 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/container-with-most-water/description/" target="_blank" rel="noopener noreferrer">力扣 11 盛最多水的容器</a></p>
<h2>题目描述</h2>
<p>给定一个长度为 <code>n</code> 的整数数组 <code>height</code> 。有 <code>n</code> 条垂线，第 <code>i</code> 条线的两个端点是 <code>(i, 0)</code> 和 <code>(i, height[i])</code> 。</p>
<p>找出其中的两条线，使得它们与 <code>x</code> 轴共同构成的容器可以容纳最多的水。</p>
<p>返回容器可以储存的最大水量。</p>
<p>**说明：**你不能倾斜容器。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：[1,8,6,2,5,4,8,3,7]</span>
<span class="line">输出：49 </span>
<span class="line">解释：图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下，容器能够容纳水（表示为蓝色部分）的最大值为 49。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：height = [1,1]</span>
<span class="line">输出：1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>n == height.length</code></li>
<li><code>2 &lt;= n &lt;= 105</code></li>
<li><code>0 &lt;= height[i] &lt;= 104</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个使用双指针的题目</li>
<li>使用索引 <code>i</code> 从 <code>height</code> 数组的左侧开始遍历，<code>i</code> 的初始值为 0</li>
<li>使用索引 <code>j</code> 从 <code>height</code> 数组的右侧开始遍历，<code>j</code> 的初始值为 n - 1，其中 n 为数组长度</li>
<li>使用 <code>res</code> 保存当前的最大值，如果 <code>min(height[i], height[j]) * (j-i)</code> 大于当前的 <code>res</code> 那么就更新 <code>res</code> 的值</li>
<li>如果这时候 <code>height[i]</code> 更短一些，那么就尝试着向右移动 <code>i</code> 去寻找更长的左侧板子</li>
<li>如果这时候 <code>height[j]</code> 更短一些，那么就尝试着向左移动 <code>j</code> 去寻找更长的右侧板子</li>
<li>关于这种操作会不会漏掉一些其他的情况：当 <code>height[i]</code> 更短一些的时候，如果我们不选择移动 <code>i</code> 而是选择向左移动 <code>j</code>，那么你可以知道，底边的长度是必然会变小的，然而在向左移动 <code>j</code> 的过程中只会出现两种情况</li>
<li>（1）<code>height[j]</code> 变得更长了，但是这并没有用，因为<code>height[i]</code> 是短板，而且底边也在变小，所以并不能使得 <code>res</code> 变大；</li>
<li>（2）<code>height[j]</code> 变得更短了，甚至比 <code>height[i]</code> 还要短，这就更糟糕了，因为 <code>height[j]</code> 变成了短板，而且底边也在不断的变小；</li>
<li>经过以上分析，我们可以知道，我们可以直接排除掉这些不必要的运算过程，所以我们的方法是没有问题的。</li>
<li>关于这一点，在力扣上有一个题解很不错，可以参考：</li>
</ul>
<p>题解传送门：<a href="https://leetcode.cn/problems/container-with-most-water/solutions/11491/container-with-most-water-shuang-zhi-zhen-fa-yi-do/" target="_blank" rel="noopener noreferrer">11 盛最多水的容器题解</a></p>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int maxArea(vector&lt;int&gt;&amp; height) {</span>
<span class="line">        int i = 0;</span>
<span class="line">        int j = height.size() - 1;</span>
<span class="line"></span>
<span class="line">        int res = 0;</span>
<span class="line"></span>
<span class="line">        while( i &lt; j ) {</span>
<span class="line">            if( height[i] &gt; height[j] ) {</span>
<span class="line">                res = max(res, (j-i) * height[j]);</span>
<span class="line">                j--;</span>
<span class="line">            } else {</span>
<span class="line">                // height[i] &lt; height[j]</span>
<span class="line">                res = max(res, (j-i) * height[i]);</span>
<span class="line">                i++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0209 长度最小的子数组</title>
      <link>https://blueberry-universe.cn/2024-12-31-00/</link>
      <guid>https://blueberry-universe.cn/2024-12-31-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0209 长度最小的子数组</source>
      <description>0209 长度最小的子数组
你好啊，我是蓝莓，今天是每日一题的第 12 天。
题目清单：一起刷力扣
引用力扣题目：209 长度最小的子数组
题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的
子数组
[numsl, numsl+1, ..., numsr-1, numsr...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 12 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/minimum-size-subarray-sum/description/" target="_blank" rel="noopener noreferrer">209 长度最小的子数组</a></p>
<h2>题目描述</h2>
<p>给定一个含有 <code>n</code> 个正整数的数组和一个正整数 <code>target</code> <strong>。</strong></p>
<p>找出该数组中满足其总和大于等于 <code>target</code> 的长度最小的</p>
<p><strong>子数组</strong></p>
<p><code>[numsl, numsl+1, ..., numsr-1, numsr]</code> ，并返回其长度**。**如果不存在符合条件的子数组，返回 <code>0</code> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：target = 7, nums = [2,3,1,2,4,3]</span>
<span class="line">输出：2</span>
<span class="line">解释：子数组 [4,3] 是该条件下的长度最小的子数组。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：target = 4, nums = [1,4,4]</span>
<span class="line">输出：1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：target = 11, nums = [1,1,1,1,1,1,1,1]</span>
<span class="line">输出：0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= target &lt;= 109</code></li>
<li><code>1 &lt;= nums.length &lt;= 105</code></li>
<li><code>1 &lt;= nums[i] &lt;= 104</code></li>
</ul>
<p><strong>进阶：</strong></p>
<ul>
<li>如果你已经实现 <code>O(n)</code> 时间复杂度的解法, 请尝试设计一个 <code>O(n log(n))</code> 时间复杂度的解法。</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>使用滑动窗口</li>
<li>使用索引 <code>l</code> 代表窗口的左边界</li>
<li>使用索引 <code>r</code> 代表窗口的右边界</li>
<li>区间 <code>nums[l...r)</code> 代表窗口内的元素，<code>r-l</code> 是窗口的大小，<code>r</code> 的取值应该小于等于 <code>len(nums)</code></li>
<li>使用 <code>sum</code> 记录窗口内元素的总和</li>
<li>当 <code>sum</code> 的值小于 <code>target</code> 的时候，说明窗口内的元素不够，这时候应该向右移动 <code>r</code> 来扩大窗口</li>
<li>当 <code>sum</code> 的值大于等于 <code>target</code> 的时候，比较当前的窗口长度是不是更小了，如果更小则更新窗口的最小长度，否则的话不需要更新；然后尝试着减小窗口的大小，也就是向右移动 <code>l</code>；</li>
<li>关于这种方法的正确性依然可以使用搜索空间的角度来思考</li>
<li>因为一开始的时候，<code>nums[l...r)</code> 内的元素总和不够，所以只能向右移动 <code>r</code> 扩展区间的大小，进而让总和变得更大</li>
<li>当总和满足要求的时候，我们为了找到更小的长度，这时候尝试着让 <code>l</code> 向右移动</li>
<li>这时候会漏掉一些情况吗？不会的，因为只要 <code>r</code> 不在当前位置，而是向左缩了一点，都不可能让这个区间内的元素总和满足要求的，所以我们可以排除掉很多的选项。</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int minSubArrayLen(int target, vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        int l = 0;</span>
<span class="line">        int r = 0;</span>
<span class="line"></span>
<span class="line">        int sum = 0;</span>
<span class="line">        int res = INT_MAX;</span>
<span class="line">        </span>
<span class="line">        // 维护区间 nums[l...r)</span>
<span class="line">        while( l &lt; nums.size() ) {</span>
<span class="line">            if( sum &lt; target ) {</span>
<span class="line">                // sum &lt; target 但是 已经没法再继续扩展了</span>
<span class="line">                if( r &gt;= nums.size() ) break;</span>
<span class="line"></span>
<span class="line">                r++;</span>
<span class="line">                sum += nums[r-1];</span>
<span class="line">            } else {</span>
<span class="line">                res = min(res, r-l);</span>
<span class="line">                sum -= nums[l];</span>
<span class="line">                l++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( res == INT_MAX ) return 0;</span>
<span class="line">        </span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0209 长度最小的子数组</title>
      <link>https://blueberry-universe.cn/2024-12-31-01/</link>
      <guid>https://blueberry-universe.cn/2024-12-31-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0209 长度最小的子数组</source>
      <description>0209 长度最小的子数组
你好啊，我是蓝莓，今天是每日一题的第 13 天。
题目清单：一起刷力扣
引用力扣题目：169 多数元素
题目描述
给定一个大小为 n 的数组 nums ，返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的，并且给定的数组总是存在多数元素。
示例 1：

示例 2：

提示...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 13 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/majority-element/?envType=study-plan-v2&amp;envId=top-interview-150" target="_blank" rel="noopener noreferrer">169 多数元素</a></p>
<h2>题目描述</h2>
<p>给定一个大小为 <code>n</code> 的数组 <code>nums</code> ，返回其中的多数元素。多数元素是指在数组中出现次数 <strong>大于</strong> <code>⌊ n/2 ⌋</code> 的元素。</p>
<p>你可以假设数组是非空的，并且给定的数组总是存在多数元素。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [3,2,3]</span>
<span class="line">输出：3</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [2,2,1,1,1,2,2]</span>
<span class="line">输出：2</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>n == nums.length</code></li>
<li><code>1 &lt;= n &lt;= 5 * 104</code></li>
<li><code>-109 &lt;= nums[i] &lt;= 109</code></li>
</ul>
<p>**进阶：**尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。</p>
<h2>实现</h2>
<p><strong>思考</strong></p>
<ul>
<li>使用 哈希表 来记录扫描过程中每个元素出现的次数</li>
<li>如果的统计过程中，发现某个元素的出现次数已经属于多数元素了，直接返回即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int majorityElement(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line">        int target = nums.size() / 2;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            record[nums[i]]++;</span>
<span class="line">            if( record[nums[i]] &gt; target ) {</span>
<span class="line">                return nums[i];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return -1;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0189 轮转数组</title>
      <link>https://blueberry-universe.cn/2024-12-31-02/</link>
      <guid>https://blueberry-universe.cn/2024-12-31-02/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0189 轮转数组</source>
      <description>0189 轮转数组
你好啊，我是蓝莓，今天是每日一题的第 14 天。
题目清单：一起刷力扣
引用力扣题目：189 轮转数组
题目描述
给定一个整数数组 nums，将数组中的元素向右轮转 k 个位置，其中 k 是非负数。
示例 1:

示例 2:

提示：

1 &amp;lt;= nums.length &amp;lt;= 105
-231 &amp;lt;= nums[i]...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 14 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/rotate-array/description/?envType=study-plan-v2&amp;envId=top-interview-150" target="_blank" rel="noopener noreferrer">189 轮转数组</a></p>
<h2>题目描述</h2>
<p>给定一个整数数组 <code>nums</code>，将数组中的元素向右轮转 <code>k</code> 个位置，其中 <code>k</code> 是非负数。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: nums = [1,2,3,4,5,6,7], k = 3</span>
<span class="line">输出: [5,6,7,1,2,3,4]</span>
<span class="line">解释:</span>
<span class="line">向右轮转 1 步: [7,1,2,3,4,5,6]</span>
<span class="line">向右轮转 2 步: [6,7,1,2,3,4,5]</span>
<span class="line">向右轮转 3 步: [5,6,7,1,2,3,4]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [-1,-100,3,99], k = 2</span>
<span class="line">输出：[3,99,-1,-100]</span>
<span class="line">解释: </span>
<span class="line">向右轮转 1 步: [99,-1,-100,3]</span>
<span class="line">向右轮转 2 步: [3,99,-1,-100]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 105</code></li>
<li><code>-231 &lt;= nums[i] &lt;= 231 - 1</code></li>
<li><code>0 &lt;= k &lt;= 105</code></li>
</ul>
<p><strong>进阶：</strong></p>
<ul>
<li>尽可能想出更多的解决方案，至少有 <strong>三种</strong> 不同的方法可以解决这个问题。</li>
<li>你可以使用空间复杂度为 <code>O(1)</code> 的 <strong>原地</strong> 算法解决这个问题吗？</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>k 对 <code>len(nums)</code> 取模，保证 <code>k</code> 是在有必要的轮转范围内</li>
<li>第一步，翻转整个数组</li>
<li>第二步，翻转前 k 个元素</li>
<li>第三步，翻转后 n-k 个元素</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void rotate(vector&lt;int&gt;&amp; nums, int k) {</span>
<span class="line"></span>
<span class="line">        k = k % nums.size();</span>
<span class="line"></span>
<span class="line">        // 1. 翻转整个数组</span>
<span class="line">        reverse( nums, 0, nums.size() - 1 );</span>
<span class="line"></span>
<span class="line">        // 2. 翻转前 k 个</span>
<span class="line">        reverse( nums, 0, k-1);</span>
<span class="line"></span>
<span class="line">        // 3. 翻转后 n-k 个</span>
<span class="line">        reverse( nums, k, nums.size() - 1 );</span>
<span class="line"></span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    void reverse( vector&lt;int&gt;&amp; nums, int i, int j ) {</span>
<span class="line">        while( i &lt; j ) {</span>
<span class="line">            swap(nums[i++], nums[j--]);</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0003 无重复字符的最长子串</title>
      <link>https://blueberry-universe.cn/2025-01-05-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-05-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0003 无重复字符的最长子串</source>
      <description>0003 无重复字符的最长子串
你好啊，我是蓝莓，今天是每日一题的第 15 天。
题目清单：一起刷力扣
引用力扣题目：3 无重复字符的最长子串
题目描述
给定一个字符串 s ，请你找出其中不含有重复字符的 最长子串
的长度。
示例 1:

示例 2:

示例 3:

提示：

0 &amp;lt;= s.length &amp;lt;= 5 * 104
s 由英文字母...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 15 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/" target="_blank" rel="noopener noreferrer">3 无重复字符的最长子串</a></p>
<h2>题目描述</h2>
<p>给定一个字符串 <code>s</code> ，请你找出其中不含有重复字符的 <strong>最长子串</strong></p>
<p>的长度。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "abcabcbb"</span>
<span class="line">输出: 3 </span>
<span class="line">解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "bbbbb"</span>
<span class="line">输出: 1</span>
<span class="line">解释: 因为无重复字符的最长子串是 "b"，所以其长度为 1。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "pwwkew"</span>
<span class="line">输出: 3</span>
<span class="line">解释: 因为无重复字符的最长子串是 "wke"，所以其长度为 3。</span>
<span class="line">     请注意，你的答案必须是 子串 的长度，"pwke" 是一个子序列，不是子串。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>0 &lt;= s.length &lt;= 5 * 104</code></li>
<li><code>s</code> 由英文字母、数字、符号和空格组成</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>使用滑动窗口 + 记录每个字符在窗口内出现的次数</li>
<li>使用索引 <code>i</code> 代表窗口的左边界，使用索引 <code>j</code> 代表窗口的右边界，维护区间 <code>[i...j]</code> 为窗口</li>
<li>当纳入新的元素到窗口中的时候，如果发现该元素已经出现过一次了，那就从窗口的左侧开始缩小窗口，直到将该元素移出窗口的范围</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int lengthOfLongestSubstring(string s) {</span>
<span class="line">        int res = 0;</span>
<span class="line">        int record[256];</span>
<span class="line"></span>
<span class="line">        for( int k = 0 ; k &lt; 256 ; k++ ) {</span>
<span class="line">            record[k] = 0;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 维护闭区间 [i...j] 为窗口</span>
<span class="line">        for( int i = 0, j = 0 ; j &lt; s.size() ; j++ ) {</span>
<span class="line">            record[s[j]]++;</span>
<span class="line">			</span>
<span class="line">            // 跳过重复元素</span>
<span class="line">            while(record[s[j]] &gt; 1) record[s[i++]]--;</span>
<span class="line">            </span>
<span class="line">            res = max(res, j-i+1);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0438 找到字符串中所有字母异位词</title>
      <link>https://blueberry-universe.cn/2025-01-06-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-06-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0438 找到字符串中所有字母异位词</source>
      <description>0438 找到字符串中所有字母异位词
你好啊，我是蓝莓，今天是每日一题的第 16 天。
题目清单：一起刷力扣
引用力扣题目：438 找到字符串中所有字母异位词
题目描述
给定两个字符串 s 和 p，找到 s 中所有 p 的
异位词
的子串，返回这些子串的起始索引。不考虑答案输出的顺序。
示例 1:

示例 2:

提示:

1 &amp;lt;= s.leng...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 16 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/" target="_blank" rel="noopener noreferrer">438 找到字符串中所有字母异位词</a></p>
<h2>题目描述</h2>
<p>给定两个字符串 <code>s</code> 和 <code>p</code>，找到 <code>s</code> 中所有 <code>p</code> 的</p>
<p><strong>异位词</strong></p>
<p>的子串，返回这些子串的起始索引。不考虑答案输出的顺序。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "cbaebabacd", p = "abc"</span>
<span class="line">输出: [0,6]</span>
<span class="line">解释:</span>
<span class="line">起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。</span>
<span class="line">起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "abab", p = "ab"</span>
<span class="line">输出: [0,1,2]</span>
<span class="line">解释:</span>
<span class="line">起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。</span>
<span class="line">起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。</span>
<span class="line">起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= s.length, p.length &lt;= 3 * 104</code></li>
<li><code>s</code> 和 <code>p</code> 仅包含小写字母</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>使用定长的滑动窗口，滑动窗口的长度为我们要寻找的异位词的字符串的长度，也就是字符串 p 的长度</li>
<li>使用 <code>record</code> 数组来记录对每个 p 字符串中的字符，每个字符还需要多少个才能满足要求</li>
<li>在字符串 s 上进行滑动，每个被我们滑进窗口的字符对应在 <code>record</code> 中的记录就减少 1 ，因为这时候我们已经找到了一个字符。当然啦，有的字符可能是不需要的，一开始的需求量就是 0，所以这时候某些字符会的需求量会变为负数，也就是需求过剩了</li>
<li>每当我们完成一次滑动之后，我们就检查这个 <code>record</code> 中的记录是否都为 0，如果不是都为 0 的话，说明是不匹配的</li>
<li>窗口的长度已经固定了，所以只有 <code>record</code> 中的记录都为 0 的时候才是满足要求的</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; findAnagrams(string s, string p) {</span>
<span class="line">        </span>
<span class="line">        // 保证 p 的长度是小于等于 s 的</span>
<span class="line">        if(p.size() &gt; s.size()) {</span>
<span class="line">            return vector&lt;int&gt;();</span>
<span class="line">        }</span>
<span class="line">        </span>
<span class="line">        int record[26];  // 分别对 26 个字母还需要多少</span>
<span class="line">        vector&lt;int&gt; res;  // 保存结果</span>
<span class="line"></span>
<span class="line">        // 数组置空</span>
<span class="line">        memset(record, 0, sizeof(record));</span>
<span class="line"></span>
<span class="line">        // 记录原始需求</span>
<span class="line">        for( int i = 0 ; i &lt; p.size() ; i++ ) {</span>
<span class="line">            record[p[i]-'a']++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 使用定长的滑动窗口</span>
<span class="line">        // 初始化一开始的窗口中的记录</span>
<span class="line">        for( int i = 0 ; i &lt; p.size() ; i++ ) {</span>
<span class="line">            record[s[i]-'a']--;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 窗口的区间是 [l...r]</span>
<span class="line">        int l = 0;</span>
<span class="line">        int r = p.size() - 1;</span>
<span class="line"></span>
<span class="line">        while( true ) {</span>
<span class="line">            // 检查当前是否满足要求</span>
<span class="line">            int ok = true;</span>
<span class="line">            for( int i = 0 ; i &lt; 26 ; i++ ) {</span>
<span class="line">                if(record[i] != 0) {</span>
<span class="line">                    ok = false;</span>
<span class="line">                    break;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            if(ok) {</span>
<span class="line">                res.push_back(l);</span>
<span class="line">            }</span>
<span class="line">            </span>
<span class="line">            if(r+1 &lt; s.size()) {</span>
<span class="line">                // 将左侧的字母移除, 对该字母的需求恢复 1</span>
<span class="line">                record[s[l++]-'a']++;</span>
<span class="line">                // 纳入新的元素到窗口中, 说明对该字母的需求减少 1</span>
<span class="line">                record[s[++r]-'a']--;</span>
<span class="line">            } else {</span>
<span class="line">                // 说明已经滑动结束了</span>
<span class="line">                break;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0076 最小覆盖子串</title>
      <link>https://blueberry-universe.cn/2025-01-06-01/</link>
      <guid>https://blueberry-universe.cn/2025-01-06-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0076 最小覆盖子串</source>
      <description>0076 最小覆盖子串
你好啊，我是蓝莓，今天是每日一题的第 17 天。
题目清单：一起刷力扣
引用力扣题目：76 最小覆盖子串
题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串，则返回空字符串 &amp;quot;&amp;quot; 。
注意：

对于 t 中重复字符，我们寻找的...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 17 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/minimum-window-substring/description/" target="_blank" rel="noopener noreferrer">76 最小覆盖子串</a></p>
<h2>题目描述</h2>
<p>给你一个字符串 <code>s</code> 、一个字符串 <code>t</code> 。返回 <code>s</code> 中涵盖 <code>t</code> 所有字符的最小子串。如果 <code>s</code> 中不存在涵盖 <code>t</code> 所有字符的子串，则返回空字符串 <code>&quot;&quot;</code> 。</p>
<p><strong>注意：</strong></p>
<ul>
<li>对于 <code>t</code> 中重复字符，我们寻找的子字符串中该字符数量必须不少于 <code>t</code> 中该字符数量。</li>
<li>如果 <code>s</code> 中存在这样的子串，我们保证它是唯一的答案。</li>
</ul>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = "ADOBECODEBANC", t = "ABC"</span>
<span class="line">输出："BANC"</span>
<span class="line">解释：最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = "a", t = "a"</span>
<span class="line">输出："a"</span>
<span class="line">解释：整个字符串 s 是最小覆盖子串。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "a", t = "aa"</span>
<span class="line">输出: ""</span>
<span class="line">解释: t 中两个字符 'a' 均应包含在 s 的子串中，</span>
<span class="line">因此没有符合条件的子字符串，返回空字符串。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>m == s.length</code></li>
<li><code>n == t.length</code></li>
<li><code>1 &lt;= m, n &lt;= 105</code></li>
<li><code>s</code> 和 <code>t</code> 由英文字母组成</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>使用可变的滑动窗口</li>
<li>这个题目和 438 号题目的题解类似，我们使用 <code>record</code> 记录对于每个字符的需求量</li>
<li>首先使用 <code>t</code> 字符串初始化一开始对每个字符的需求量都是多大</li>
<li>然后遍历 <code>s</code> 字符串，在窗口滑动的过程中分为两种情况</li>
<li>（1）当前如果不满足要求的话，那么就扩大窗口的范围，同时维护 <code>record</code> 中的记录</li>
<li>（2）如果当前已经满足要求了，那么我们就判断下，当前发现的子串的长度是不是比我们之前找到的子串的长度还要小，如果还要小的话就更新一下子串的起始位置和长度。接着，我们这时候不再扩大窗口了，我们尝试着缩小窗口去寻找更短的满足要求的子串</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    string minWindow(string s, string t) {</span>
<span class="line">        if( s.size() &lt; t.size() ) {</span>
<span class="line">            return &quot;&quot;;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int record[256];</span>
<span class="line"></span>
<span class="line">        // 数组置空</span>
<span class="line">        memset(record, 0, sizeof(record));</span>
<span class="line"></span>
<span class="line">        // 初始化原始需求量</span>
<span class="line">        for( int i = 0 ; i &lt; t.size() ; i++ ) {</span>
<span class="line">            record[t[i]]++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 维护区间 [l...r)</span>
<span class="line">        int l = 0;</span>
<span class="line">        int r = 0;</span>
<span class="line"></span>
<span class="line">        // 记录最小覆盖子串的起始位置</span>
<span class="line">        int start = -1;</span>
<span class="line">        // 记录最小覆盖子串的长度</span>
<span class="line">        int minimum_size = INT_MAX;</span>
<span class="line"></span>
<span class="line">        while( r &lt;= s.size() ) {</span>
<span class="line">            bool ok = true;</span>
<span class="line"></span>
<span class="line">            // 检查是否满足要求</span>
<span class="line">            for( int i = 'A' ; i &lt;= 'z' ; i++ ) {</span>
<span class="line">                if( record[i] &gt; 0 ) {</span>
<span class="line">                    ok = false;</span>
<span class="line">                    break;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            if(ok) {</span>
<span class="line">                // 记录当前的最小字符串</span>
<span class="line">                if( minimum_size &gt; r-l ) {</span>
<span class="line">                    minimum_size = r-l;</span>
<span class="line">                    start = l;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                // 当前已经满足要求 尝试缩小窗口的大小</span>
<span class="line">                record[s[l++]]++;</span>
<span class="line">            } else {</span>
<span class="line">                // 继续扩大窗口</span>
<span class="line">                // 纳入新的元素到 record</span>
<span class="line">                // 对该元素的需求减少 1</span>
<span class="line">                record[s[r++]]--;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line">        </span>
<span class="line">        if( start == -1 ) {</span>
<span class="line">            return &quot;&quot;;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return s.substr(start, minimum_size);</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0349 两个数组的交集</title>
      <link>https://blueberry-universe.cn/2025-01-07-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-07-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0349 两个数组的交集</source>
      <description>0349 两个数组的交集
你好啊，我是蓝莓，今天是每日一题的第 18 天。
题目清单：一起刷力扣
引用力扣题目：349 两个数组的交集
题目描述
给定两个数组 nums1 和 nums2 ，返回 它们的
交集
。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1：

示例 2：

提示：

1 &amp;lt;= nums1.l...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 18 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/intersection-of-two-arrays/description/" target="_blank" rel="noopener noreferrer">349 两个数组的交集</a></p>
<h2>题目描述</h2>
<p>给定两个数组 <code>nums1</code> 和 <code>nums2</code> ，返回 <em>它们的</em></p>
<p><em>交集</em></p>
<p>。输出结果中的每个元素一定是 <strong>唯一</strong> 的。我们可以 <strong>不考虑输出结果的顺序</strong> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [1,2,2,1], nums2 = [2,2]</span>
<span class="line">输出：[2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [4,9,5], nums2 = [9,4,9,8,4]</span>
<span class="line">输出：[9,4]</span>
<span class="line">解释：[4,9] 也是可通过的</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums1.length, nums2.length &lt;= 1000</code></li>
<li><code>0 &lt;= nums1[i], nums2[i] &lt;= 1000</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个简单题，可以通过这个题目熟悉一下编程语言中集合的使用方法</li>
<li>最简单的思路就是使用两个 <code>set</code> 分别对 <code>nums1</code> 和 <code>nums2</code> 去重</li>
<li>然后求两个集合的交集即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; intersection(vector&lt;int&gt;&amp; nums1, vector&lt;int&gt;&amp; nums2) {</span>
<span class="line">        set&lt;int&gt; record1;</span>
<span class="line">        set&lt;int&gt; record2;</span>
<span class="line">        </span>
<span class="line">        vector&lt;int&gt; res;</span>
<span class="line"></span>
<span class="line">        // 对 nums1 去重</span>
<span class="line">        for( int num : nums1 ) {</span>
<span class="line">            record1.insert(num);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 对 nums2 去重</span>
<span class="line">        for( int num : nums2 ) {</span>
<span class="line">            record2.insert(num);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 遍历集合 record2 中的元素，看看是不是在 record1 集合中也出现了</span>
<span class="line">        // 如果同时满足 则这个就纳入 res 中</span>
<span class="line">        for( set&lt;int&gt;::iterator iter = record2.begin() ; iter != record2.end() ; iter++ ) {</span>
<span class="line">            if( record1.find(*iter) != record1.end() ) {</span>
<span class="line">                res.push_back(*iter);</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0350 两个数组的交集 II</title>
      <link>https://blueberry-universe.cn/2025-01-09-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-09-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0350 两个数组的交集 II</source>
      <description>0350 两个数组的交集 II
你好啊，我是蓝莓，今天是每日一题的第 19 天。
题目清单：一起刷力扣
引用力扣题目：350 两个数组的交集 II
题目描述
给你两个整数数组 nums1 和 nums2 ，请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数，应与元素在两个数组中都出现的次数一致（如果出现次数不一致，则考虑取较小值）。可以不考虑...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 19 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/intersection-of-two-arrays-ii/description/" target="_blank" rel="noopener noreferrer">350 两个数组的交集 II</a></p>
<h2>题目描述</h2>
<p>给你两个整数数组 <code>nums1</code> 和 <code>nums2</code> ，请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数，应与元素在两个数组中都出现的次数一致（如果出现次数不一致，则考虑取较小值）。可以不考虑输出结果的顺序。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [1,2,2,1], nums2 = [2,2]</span>
<span class="line">输出：[2,2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [4,9,5], nums2 = [9,4,9,8,4]</span>
<span class="line">输出：[4,9]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums1.length, nums2.length &lt;= 1000</code></li>
<li><code>0 &lt;= nums1[i], nums2[i] &lt;= 1000</code></li>
</ul>
<p><strong><em>*进阶*</em>：</strong></p>
<ul>
<li>如果给定的数组已经排好序呢？你将如何优化你的算法？</li>
<li>如果 <code>nums1</code> 的大小比 <code>nums2</code> 小，哪种方法更优？</li>
<li>如果 <code>nums2</code> 的元素存储在磁盘上，内存是有限的，并且你不能一次加载所有的元素到内存中，你该怎么办？</li>
</ul>
<h2>实现</h2>
<p><strong>方法 1 思路</strong></p>
<ul>
<li>这是一个评分为简单的题目。</li>
<li>最简单的方法，我们使用分别使用 <code>map1</code>  和 <code>map2</code> 来统计 <code>nums1</code> 和 <code>nums1</code> 中每个数值出现的次数</li>
<li>然后，遍历 <code>map1</code> 或者 <code>map2</code> 任意一个都是可以的，我们需要找到既存在 <code>map1</code> 中也存在 <code>map2</code> 中的 <code>key</code>，然后向结果中添加两者出现的 <code>key</code> 的次数较小的那个作为添加的次数即可</li>
<li>这个题目其实主要是让我们熟悉使用 <code>map</code> 这种数据结构；在 <code>C++</code> 的代码中，如果 <code>map[key]</code> 这个元素不存在的话，那么就会自动在数据结构中添加键为 <code>key</code> 并且初始值为 <code>0</code> 的值 （这是对于 key 和 value 都是 int 类型而言的），所以我的代码才写成了这样</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; intersect(vector&lt;int&gt;&amp; nums1, vector&lt;int&gt;&amp; nums2) {</span>
<span class="line">        unordered_map&lt;int, int&gt; map1;</span>
<span class="line">        unordered_map&lt;int, int&gt; map2;</span>
<span class="line">        vector&lt;int&gt; res;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums1.size() ; i++ ) {</span>
<span class="line">            map1[nums1[i]]++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums2.size() ; i++ ) {</span>
<span class="line">            map2[nums2[i]]++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 遍历 map1</span>
<span class="line">        for( auto iter = map1.begin() ; iter != map1.end() ; iter++ ) {</span>
<span class="line">            int key = iter-&gt;first;</span>
<span class="line">            int value = iter-&gt;second;</span>
<span class="line"></span>
<span class="line">            if( map2.find(key) != map2.end() ) {</span>
<span class="line">                int sz = min(value, map2[key]);</span>
<span class="line">                for( int k = 0 ; k &lt; sz ; k++ ) {</span>
<span class="line">                    res.push_back( key );</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>方法 2 思路</strong></p>
<ul>
<li>我们也可以只统计 <code>nums1</code> 数组中每个元素出现的次数</li>
<li>然后我们遍历 <code>nums2</code> 数组就可以了，每当我们遍历到一项的时候，我们就去 <code>map</code> 数据结构中找一找，看看 <code>nums1</code> 中存不存在这个数？如果存在的话我们就把这个数添加到结果中去</li>
<li>但是，这里要注意了，比如 <code>10</code> 这个数在 <code>nums1</code> 中出现了 20 次，但是在 <code>nums2</code> 中出现了 <code>30</code> 次，那么我们就会在 <code>nums2</code> 中遍历到 <code>30</code> 次这个数了。这样就会在结果中添加 <code>30</code> 次，显然不符合题意。</li>
<li>所以，我们每次添加完成一个数的时候，我们就把 <code>map</code> 中的计数减少 1，只有我们查找到的这个数在 <code>nums1</code> 的 <code>map</code> 剩余的次数大于 0 的时候，我们才把这个数纳入结果中去</li>
</ul>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; intersect(vector&lt;int&gt;&amp; nums1, vector&lt;int&gt;&amp; nums2) {</span>
<span class="line">        // 时间复杂度 : O(1)</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums1.size(); i++ ) {</span>
<span class="line">            if( record.find(nums1[i]) == record.end() ) {</span>
<span class="line">                record.insert( make_pair(nums1[i], 1) );</span>
<span class="line">            } else {</span>
<span class="line">                record[nums1[i]] ++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        vector&lt;int&gt; res;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums2.size() ; i++ ) {</span>
<span class="line">            if( record.find( nums2[i] ) != record.end() &amp;&amp; record[nums2[i]] &gt; 0 ) {</span>
<span class="line">                record[nums2[i]] --;</span>
<span class="line">                res.push_back( nums2[i] );</span>
<span class="line">                if( record[nums2[i]] == 0 ) {</span>
<span class="line">                    record.erase( nums2[i] );</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0242 有效的字母异位词</title>
      <link>https://blueberry-universe.cn/2025-01-10-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-10-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0242 有效的字母异位词</source>
      <description>0242 有效的字母异位词
你好啊，我是蓝莓，今天是每日一题的第 20 天。
题目清单：一起刷力扣
引用力扣题目：242 有效的字母异位词
题目描述
给定两个字符串 s 和 t ，编写一个函数来判断 t 是否是 s 的
字母异位词
。
示例 1:

示例 2:

提示:

1 &amp;lt;= s.length, t.length &amp;lt;= 5 * 104...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 20 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/valid-anagram/description/" target="_blank" rel="noopener noreferrer">242 有效的字母异位词</a></p>
<h2>题目描述</h2>
<p>给定两个字符串 <code>s</code> 和 <code>t</code> ，编写一个函数来判断 <code>t</code> 是否是 <code>s</code> 的</p>
<p>字母异位词</p>
<p>。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "anagram", t = "nagaram"</span>
<span class="line">输出: true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "rat", t = "car"</span>
<span class="line">输出: false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= s.length, t.length &lt;= 5 * 104</code></li>
<li><code>s</code> 和 <code>t</code> 仅包含小写字母</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个简单题，可以用来练习使用 <code>map</code></li>
<li>我们可以先使用 <code>map</code> 统计字符串 <code>s</code> 中每个字符出现的频率</li>
<li>然后，遍历字符串 <code>t</code> ，对于 <code>t</code> 中出现的字符是必须在 <code>s</code> 中出现相同次数的，每遍历到一个字符，我们就对 <code>map</code> 中统计到的频率进行减1的操作</li>
<li>如果我们发现一个字符在 <code>map</code> 中的频率已经小于等于 0 了，那就说明 <code>s</code> 字符串中的字符的个数不满足要求，就可以直接返回 <code>false</code> 了</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isAnagram(string s, string t) {</span>
<span class="line">        unordered_map&lt;char, int&gt; record;</span>
<span class="line">		</span>
<span class="line">        // 首先要保证 s 和 t 的长度是一直的才行</span>
<span class="line">        if( s.size() != t.size() ) {</span>
<span class="line">            return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; s.size() ; i++ ) {</span>
<span class="line">            record[s[i]]++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; t.size() ; i++ ) {</span>
<span class="line">            if( record.find(t[i]) != record.end() &amp;&amp; record[t[i]] &gt; 0 ) {</span>
<span class="line">                // 匹配的情况下对频率进行减 1 操作</span>
<span class="line">                record[t[i]]--;</span>
<span class="line">            } else {</span>
<span class="line">                // 比匹配的情况下返回 false</span>
<span class="line">                return false;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line">		</span>
<span class="line">        // 如果字符串 t 已经遍历完了也没有发现不匹配的则说明匹配成功</span>
<span class="line">        return true;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0202 快乐数</title>
      <link>https://blueberry-universe.cn/2025-01-13-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-13-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0202 快乐数</source>
      <description>0202 快乐数
你好啊，我是蓝莓，今天是每日一题的第 21 天。
题目清单：一起刷力扣
引用力扣题目：202 快乐数
题目描述
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为：

对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。
如果这个过程 ...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 21 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/happy-number/description/" target="_blank" rel="noopener noreferrer">202 快乐数</a></p>
<h2>题目描述</h2>
<p>编写一个算法来判断一个数 <code>n</code> 是不是快乐数。</p>
<p><strong>「快乐数」</strong> 定义为：</p>
<ul>
<li>对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和。</li>
<li>然后重复这个过程直到这个数变为 1，也可能是 <strong>无限循环</strong> 但始终变不到 1。</li>
<li>如果这个过程 <strong>结果为</strong> 1，那么这个数就是快乐数。</li>
</ul>
<p>如果 <code>n</code> 是 <em>快乐数</em> 就返回 <code>true</code> ；不是，则返回 <code>false</code> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 19</span>
<span class="line">输出：true</span>
<span class="line">解释：</span>
<span class="line">12 + 92 = 82</span>
<span class="line">82 + 22 = 68</span>
<span class="line">62 + 82 = 100</span>
<span class="line">12 + 02 + 02 = 1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 2</span>
<span class="line">输出：false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= n &lt;= 231 - 1</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个简单题，只需要按着题目来做即可</li>
<li>主要可以学习一下怎么取一个数值的十进制表示情况下的各个位置上的数值</li>
<li>为了防止死循环，我们需要对之前已经迭代过得数值做一个记录，直接使用 哈希表 即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isHappy(int n) {</span>
<span class="line">        </span>
<span class="line">        unordered_set&lt;int&gt; record;</span>
<span class="line">        record.insert(n);</span>
<span class="line"></span>
<span class="line">        // 假设上一次得到的数值为 sum</span>
<span class="line">        int sum = n;</span>
<span class="line"></span>
<span class="line">        while( true ) {</span>
<span class="line">            </span>
<span class="line">            // 把上一次得到的数值 sum 放在 n 里面</span>
<span class="line">            n = sum;</span>
<span class="line">            // 重新计算各个位置上的数值平方的和</span>
<span class="line">            sum = 0;</span>
<span class="line"></span>
<span class="line">            // 只要 n 还是大于 0 的 那就不停地取末尾数值</span>
<span class="line">            while( n &gt; 0 ) {</span>
<span class="line">                int res = n % 10;</span>
<span class="line">                n = n / 10;</span>
<span class="line">                sum += res * res;    </span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 如果已经发现等于 1 了 说明是快乐数 直接返回</span>
<span class="line">            if( sum == 1 ) return true;</span>
<span class="line"></span>
<span class="line">            // 如果发现这个数值 在之前已经得到过了 那就没必要继续下去了</span>
<span class="line">            // 会造成死循环 说明这不是一个快乐数</span>
<span class="line">            if( record.find(sum) != record.end() ) {</span>
<span class="line">                return false;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 记录下当前迭代到的数值 sum</span>
<span class="line">            record.insert( sum );</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return false;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0290 单词规律</title>
      <link>https://blueberry-universe.cn/2025-01-14-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-14-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0290 单词规律</source>
      <description>0290 单词规律
你好啊，我是蓝莓，今天是每日一题的第 22 天。
题目清单：一起刷力扣
引用力扣题目：290 单词规律
题目描述
给定一种规律 pattern 和一个字符串 s ，判断 s 是否遵循相同的规律。
这里的 遵循 指完全匹配，例如， pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。
示例1:

示...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 22 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/word-pattern/description/" target="_blank" rel="noopener noreferrer">290 单词规律</a></p>
<h2>题目描述</h2>
<p>给定一种规律 <code>pattern</code> 和一个字符串 <code>s</code> ，判断 <code>s</code> 是否遵循相同的规律。</p>
<p>这里的 <strong>遵循</strong> 指完全匹配，例如， <code>pattern</code> 里的每个字母和字符串 <code>s</code> 中的每个非空单词之间存在着双向连接的对应规律。</p>
<p><strong>示例1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: pattern = "abba", s = "dog cat cat dog"</span>
<span class="line">输出: true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入:pattern = "abba", s = "dog cat cat fish"</span>
<span class="line">输出: false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: pattern = "aaaa", s = "dog cat cat dog"</span>
<span class="line">输出: false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= pattern.length &lt;= 300</code></li>
<li><code>pattern</code> 只包含小写英文字母</li>
<li><code>1 &lt;= s.length &lt;= 3000</code></li>
<li><code>s</code> 只包含小写英文字母和 <code>' '</code></li>
<li><code>s</code> <strong>不包含</strong> 任何前导或尾随对空格</li>
<li><code>s</code> 中每个单词都被 <strong>单个空格</strong> 分隔</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>按照题目的要求来做这个题目就可以了</li>
<li>需要我们使用两个 <code>map</code> 来记录映射关系</li>
<li>第一个映射关系是从 <code>pattern</code> 中的单个 <code>char</code> 到 <code>s</code> 字符串中的单个 <code>word</code></li>
<li>第二个映射关系是从 <code>s</code> 中的单个 <code>word</code> 到 <code>pattern</code> 中的单个 <code>char</code></li>
<li>为什么需要记录两次映射关系？</li>
<li>这是为了保证映射的唯一，因为 <code>a</code> 可能映射到 <code>dog</code> 也可能存在 <code>cat</code> 和 <code>a</code> 是对应的</li>
<li>如果我们不同时记录两个方向的映射的话，我们就没办法保证这个映射是唯一的</li>
<li>在代码中使用 <code>forward</code> 记录第一个映射关系，使用 <code>backward</code> 记录第二个映射关系</li>
<li>遍历 <code>p</code> 字符串并且在遍历的过程中去 <code>s</code> 字符串中寻找当 <code>start</code> 指向的起始位置的这个单词的结束位置的下一个位置 <code>end</code></li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool wordPattern(string pattern, string s) {</span>
<span class="line"></span>
<span class="line">        unordered_map&lt;char, string&gt; forward;  // 从 char 到 word 的映射</span>
<span class="line">        unordered_map&lt;string, char&gt; backward;  // 从 word 到 char 的映射</span>
<span class="line"></span>
<span class="line">        int start = 0;</span>
<span class="line">        int end = 0;</span>
<span class="line">        int wordCount = 0;  // 统计遍历过的 s 中的 word 的数量</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; pattern.size() &amp;&amp; end &lt; s.size() ; i++, wordCount++ ) {</span>
<span class="line"></span>
<span class="line">            // 寻找下一个单词</span>
<span class="line">            while( s[end] != ' ' &amp;&amp; end &lt; s.size() ) end++;</span>
<span class="line"></span>
<span class="line">            // 提取出这次找到的单词</span>
<span class="line">            string word = s.substr(start, end-start);</span>
<span class="line"></span>
<span class="line">            // 为再次寻找下一个单词做准备</span>
<span class="line">            end += 1;</span>
<span class="line">            start = end;</span>
<span class="line"></span>
<span class="line">            if( forward.find(pattern[i]) != forward.end() &amp;&amp; backward.find(word) != backward.end() ) {</span>
<span class="line">                // 映射关系不唯一 返回失败</span>
<span class="line">                if( forward[pattern[i]] != word || backward[word] != pattern[i] ) return false;</span>
<span class="line">            } else {</span>
<span class="line"></span>
<span class="line">                // 双向没有同时存在映射的情况下 若其中一个方向存在映射则失败</span>
<span class="line">                if( forward.find(pattern[i]) != forward.end() || backward.find(word) != backward.end() ) {</span>
<span class="line">                    return false;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                // 两个方向都没有映射 就可以放心的添加映射了</span>
<span class="line">                forward[pattern[i]] = word;</span>
<span class="line">                backward[word] = pattern[i];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 如果 s 中的单词没有全部遍历完 或者 两者应该对应的单词的数量不一致 则返回失败</span>
<span class="line">        if( end &lt; s.size() || pattern.size() != wordCount ) {</span>
<span class="line">            return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return true;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0205 同构字符串</title>
      <link>https://blueberry-universe.cn/2025-01-15-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-15-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0205 同构字符串</source>
      <description>0205 同构字符串
你好啊，我是蓝莓，今天是每日一题的第 23 天。
题目清单：一起刷力扣
引用力扣题目：205 同构字符串
题目描述
给定两个字符串 s 和 t ，判断它们是否是同构的。
如果 s 中的字符可以按某种映射关系替换得到 t ，那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符，同时不改变字符的顺序。不同字符不能映射到同一...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 23 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/isomorphic-strings/description/" target="_blank" rel="noopener noreferrer">205 同构字符串</a></p>
<h2>题目描述</h2>
<p>给定两个字符串 <code>s</code> 和 <code>t</code> ，判断它们是否是同构的。</p>
<p>如果 <code>s</code> 中的字符可以按某种映射关系替换得到 <code>t</code> ，那么这两个字符串是同构的。</p>
<p>每个出现的字符都应当映射到另一个字符，同时不改变字符的顺序。不同字符不能映射到同一个字符上，相同字符只能映射到同一个字符上，字符可以映射到自己本身。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = "egg", t = "add"</span>
<span class="line">输出：true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = "foo", t = "bar"</span>
<span class="line">输出：false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：s = "paper", t = "title"</span>
<span class="line">输出：true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 5 * 104</code></li>
<li><code>t.length == s.length</code></li>
<li><code>s</code> 和 <code>t</code> 由任意有效的 ASCII 字符组成</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目和 <code>290</code> 号题目是一样的思路</li>
<li>使用 <code>map</code> 维护一个双向的数据结构就可以了</li>
<li>而且这个题目还不需要自己去拆分字符串中的单词</li>
<li>它只需要让字符之间拥有映射关系即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isIsomorphic(string s, string t) {</span>
<span class="line">        unordered_map&lt;char, char&gt; forward;</span>
<span class="line">        unordered_map&lt;char, char&gt; backward;</span>
<span class="line"></span>
<span class="line">        // 起码长度是要相等的</span>
<span class="line">        if( s.size() != t.size() ) {</span>
<span class="line">            return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; s.size() ; i++ ) {</span>
<span class="line">            // 看看当前是不是双向都有映射关系</span>
<span class="line">            if( forward.find(s[i]) != forward.end() &amp;&amp; backward.find(t[i]) != backward.end() ) {</span>
<span class="line">                if( forward[s[i]] != t[i] || backward[t[i]] != s[i] ) return false;</span>
<span class="line">            } else {</span>
<span class="line">                // 如果不是双向都有映射关系 但是其中一个方向出现了映射 那必然是错的</span>
<span class="line">                if( forward.find(s[i]) != forward.end() || backward.find(t[i]) != backward.end() ) return false;</span>
<span class="line"></span>
<span class="line">                // 如果都没有映射关系那么就保存当前发现的映射关系</span>
<span class="line">                forward[s[i]] = t[i];</span>
<span class="line">                backward[t[i]] = s[i];</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return true;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0451 根据字符出现频率排序</title>
      <link>https://blueberry-universe.cn/2025-01-15-01/</link>
      <guid>https://blueberry-universe.cn/2025-01-15-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0451 根据字符出现频率排序</source>
      <description>0451 根据字符出现频率排序
你好啊，我是蓝莓，今天是每日一题的第 23 天。
题目清单：一起刷力扣
引用力扣题目：451 根据字符出现频率排序
题目描述
给定一个字符串 s ，根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。
返回 已排序的字符串 。如果有多个答案，返回其中任何一个。
示例 1:

示例 ...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 23 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/sort-characters-by-frequency/description/" target="_blank" rel="noopener noreferrer">451 根据字符出现频率排序</a></p>
<h2>题目描述</h2>
<p>给定一个字符串 <code>s</code> ，根据字符出现的 <strong>频率</strong> 对其进行 <strong>降序排序</strong> 。一个字符出现的 <strong>频率</strong> 是它出现在字符串中的次数。</p>
<p>返回 <em>已排序的字符串</em> 。如果有多个答案，返回其中任何一个。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "tree"</span>
<span class="line">输出: "eert"</span>
<span class="line">解释: 'e'出现两次，'r'和't'都只出现一次。</span>
<span class="line">因此'e'必须出现在'r'和't'之前。此外，"eetr"也是一个有效的答案。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "cccaaa"</span>
<span class="line">输出: "cccaaa"</span>
<span class="line">解释: 'c'和'a'都出现三次。此外，"aaaccc"也是有效的答案。</span>
<span class="line">注意"cacaca"是不正确的，因为相同的字母必须放在一起。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: s = "Aabb"</span>
<span class="line">输出: "bbAa"</span>
<span class="line">解释: 此外，"bbaA"也是一个有效的答案，但"Aabb"是不正确的。</span>
<span class="line">注意'A'和'a'被认为是两种不同的字符。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 5 * 105</code></li>
<li><code>s</code> 由大小写英文字母和数字组成</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>首先使用哈希表来统计每个字符出现的频率，这里使用 <code>unordered_map</code> 就可以了</li>
<li>统计好频率之后，我们需要按照频率的递减顺序依次向字符串中追加字符</li>
<li>可以使用 <code>map</code> 来实现，它的底层数据结构是使用平衡二叉树来实现的</li>
<li>根据平衡二叉树的性质，我们可以知道，按照一定的顺序进行遍历各个节点的话，那么它是有序的</li>
<li>由于可能存在多个字符出现的频率都是相同的，所以我们要是用 <code>频率</code> 到 <code>字符数组</code> 的方式来存储</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    string frequencySort(string s) {</span>
<span class="line">        unordered_map&lt;char, int&gt; record;</span>
<span class="line">        map&lt;int, vector&lt;char&gt;&gt; sorted_record;</span>
<span class="line">        </span>
<span class="line">        // 先统计各个字符的频率 字符 -&gt; 频率 的映射关系存储</span>
<span class="line">        for( int i = 0 ; i &lt; s.size() ; i++ ) {</span>
<span class="line">            record[s[i]]++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 按照 频率 -&gt; 字符 的映射关系存储</span>
<span class="line">        for( auto iter = record.begin() ; iter != record.end() ; iter++ ) {</span>
<span class="line">            sorted_record[iter-&gt;second].push_back(iter-&gt;first);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        string res = &quot;&quot;;</span>
<span class="line"></span>
<span class="line">        // 按照 频率 从大到小的顺序遍历 sorted_record</span>
<span class="line">        for( auto iter = sorted_record.rbegin() ; iter != sorted_record.rend() ; iter++ ) {</span>
<span class="line">            int freq = iter-&gt;first;  // 取出这组字符的频率</span>
<span class="line">            vector&lt;char&gt;&amp; arr = iter-&gt;second;  // 获取这组字符</span>
<span class="line"></span>
<span class="line">            for( int i = 0 ; i &lt; arr.size() ; i++ ) {</span>
<span class="line">                // 把出现频率相同的字符全部都添加 freq 次到 res 的末尾</span>
<span class="line">                for( int k = 0 ; k &lt; freq ; k++ ) {</span>
<span class="line">                    res.push_back(arr[i]);</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0001 两数之和</title>
      <link>https://blueberry-universe.cn/2025-01-16-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-16-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0001 两数之和</source>
      <description>0001 两数之和
你好啊，我是蓝莓，今天是每日一题的第 24 天。
题目清单：一起刷力扣
引用力扣题目：1 两数之和
题目描述
给定一个整数数组 nums 和一个整数目标值 target，请你在该数组中找出 和为目标值 target 的那 两个 整数，并返回它们的数组下标。
你可以假设每种输入只会对应一个答案，并且你不能使用两次相同的元素。
你可以按...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 24 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/two-sum/description/" target="_blank" rel="noopener noreferrer">1 两数之和</a></p>
<h2>题目描述</h2>
<p>给定一个整数数组 <code>nums</code> 和一个整数目标值 <code>target</code>，请你在该数组中找出 <strong>和为目标值</strong> <em><code>target</code></em> 的那 <strong>两个</strong> 整数，并返回它们的数组下标。</p>
<p>你可以假设每种输入只会对应一个答案，并且你不能使用两次相同的元素。</p>
<p>你可以按任意顺序返回答案。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [2,7,11,15], target = 9</span>
<span class="line">输出：[0,1]</span>
<span class="line">解释：因为 nums[0] + nums[1] == 9 ，返回 [0, 1] 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [3,2,4], target = 6</span>
<span class="line">输出：[1,2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [3,3], target = 6</span>
<span class="line">输出：[0,1]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>2 &lt;= nums.length &lt;= 104</code></li>
<li><code>-109 &lt;= nums[i] &lt;= 109</code></li>
<li><code>-109 &lt;= target &lt;= 109</code></li>
<li><strong>只会存在一个有效答案</strong></li>
</ul>
<p>**进阶：**你可以想出一个时间复杂度小于 <code>O(n2)</code> 的算法吗？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>对于这个问题，你在第一时间想到的最简单的方法或许就是遍历所有成对的组合，然后依次检查他们是否符合要求</li>
<li>其实，我们可以使用 <code>查找表</code> 来代替寻找组合过程中的一层 <code>for</code> 循环，可以使 <code>O(N^2)</code> 的时间复杂度变为 <code>O(N)</code></li>
<li>当我们拿到 <code>nums</code> 数组中的一个值的时候，我们这时候希望知道的是，这个数组中是不是存在另外一个数值 <code>v</code> ，是的 <code>nums[i] + v</code> 等于 <code>target</code> ？那么这个 <code>v</code> 其实就是 <code>target - nums[i]</code>，其实就是在询问，在 <code>nums</code> 中是否存在一个数值为 <code>target - nums[i]</code> 呢？</li>
<li>对于这个询问，我们可以将 <code>nums</code> 中的值存储在 <code>map</code> 中，其中 <code>key</code> 是数组中的每个值，<code>value</code> 是数组中这个值对应的 <code>index</code>。这样，我们就成功的把内层使用循环遍历查找的方式转换成了访问哈希表的方式，哈希表的查找效率是 <code>O(1)</code> ，因此时间复杂度可以降维 <code>O(N)</code></li>
</ul>
<p><strong>C++ 代码实现 1</strong></p>
<ul>
<li>在代码实现上，我们先看一个比较粗糙的实现</li>
<li>在这个实现中，我们假设 <code>nums[i]</code> 对应的是两个满足要求的数值中在数组的左侧的那个值</li>
<li>我们询问查找表的那个值是位于 <code>nums</code> 数组右侧的那个值</li>
<li>但是你会发现，查找表中存储了 <code>nums</code> 数组中所有的值，这不科学，哈哈哈</li>
<li>但是这个并不会影响正确性，比如我问访问到 <code>nums[10]</code> 的时候询问查找表，发现没有满足要求的另一个数值，那么，当我们遍历到 <code>10</code> 以后的数值的时候，是不可能认为 <code>nums[10]</code> 是满足要求的，因为它是在全部的元素中进行询问的，如果 <code>nums[10]</code> 就是其中一个满足要求的值，那么必然我们遍历到 <code>nums[10]</code> 的时候就一定会得到答案</li>
</ul>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; twoSum(vector&lt;int&gt;&amp; nums, int target) {</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line"></span>
<span class="line">        // 构建查找表</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            record[nums[i]] = i;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            // 对整个 nums 数组询问是否存在 target - nums[i] 这个值 ？</span>
<span class="line">            if(record.find(target - nums[i]) != record.end()) {</span>
<span class="line">                if( i != record[target - nums[i]] ) {</span>
<span class="line">                    return vector&lt;int&gt;({i, record[target-nums[i]]});</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return vector&lt;int&gt;({-1, -1});        </span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现 2</strong></p>
<ul>
<li>其实我们没有必要对全局进行询问的，如果假设遍历过程中的 <code>nums[i]</code> 是两个满足要求的数值中靠右的那个元素，那么我们只需要对每个 <code>nums[i]</code> 去询问它左侧的所有的元素是否满足要求就可以了，这时候我们可以正向的遍历数组，同时构建哈希表即可</li>
<li>当然，如果我们假设遍历过程中的 <code>nums[i]</code> 是靠近数组左侧的那个满足要求的值，那么我们就需要反向的遍历 <code>nums</code> 数组，因为我们需要把它右侧的值都添加到查找表中</li>
</ul>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line"></span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; twoSum(vector&lt;int&gt;&amp; nums, int target) {</span>
<span class="line">        // 使用查找表</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line"></span>
<span class="line">        for( int i =  0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            int v = nums[i];</span>
<span class="line"></span>
<span class="line">            if( record.find( target - v ) != record.end() ) {</span>
<span class="line">                int res[2] = {record[target-v], i};</span>
<span class="line">                return vector&lt;int&gt;(res, res+2);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            record[v] = i;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return vector&lt;int&gt;();</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0015 三数之和</title>
      <link>https://blueberry-universe.cn/2025-01-17-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-17-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0015 三数之和</source>
      <description>0015 三数之和
你好啊，我是蓝莓，今天是每日一题的第 25 天。
题目清单：一起刷力扣
引用力扣题目：15 三数之和
题目描述
给你一个整数数组 nums ，判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ，同时还满足 nums[i] + nums[j] + nums[...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 25 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/3sum/description/" target="_blank" rel="noopener noreferrer">15 三数之和</a></p>
<h2>题目描述</h2>
<p>给你一个整数数组 <code>nums</code> ，判断是否存在三元组 <code>[nums[i], nums[j], nums[k]]</code> 满足 <code>i != j</code>、<code>i != k</code> 且 <code>j != k</code> ，同时还满足 <code>nums[i] + nums[j] + nums[k] == 0</code> 。请你返回所有和为 <code>0</code> 且不重复的三元组。</p>
<p>**注意：**答案中不可以包含重复的三元组。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [-1,0,1,2,-1,-4]</span>
<span class="line">输出：[[-1,-1,2],[-1,0,1]]</span>
<span class="line">解释：</span>
<span class="line">nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。</span>
<span class="line">nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。</span>
<span class="line">nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。</span>
<span class="line">不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。</span>
<span class="line">注意，输出的顺序和三元组的顺序并不重要。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [0,1,1]</span>
<span class="line">输出：[]</span>
<span class="line">解释：唯一可能的三元组和不为 0 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [0,0,0]</span>
<span class="line">输出：[[0,0,0]]</span>
<span class="line">解释：唯一可能的三元组和为 0 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>3 &lt;= nums.length &lt;= 3000</code></li>
<li><code>-105 &lt;= nums[i] &lt;= 105</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路 1</strong></p>
<ul>
<li>在 <code>力扣 1 两数之和</code> 题目中，我们已经知道了如何使用哈希表来减少一层循环的开销技巧</li>
<li>那么这个题目，依旧可以使用这个思路</li>
<li>最常规的做法是来三次循环，搜索所有可能的 <code>三元组</code></li>
<li>那么，使用类似的方法，我们使用两个循环搜索所有的 <code>二元组</code>，在最内层使用哈希表来减少最内层的开销</li>
<li>这样一来，时间复杂度可从 <code>O(N^3)</code> 降低为 <code>O(N^2)</code></li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;int&gt;&gt; threeSum(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line"></span>
<span class="line">        // 统计各个元素出现的次数</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            record[nums[i]] += 1;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 排序</span>
<span class="line">        sort(nums.begin(), nums.end());</span>
<span class="line"></span>
<span class="line">        // 对排序后的元素去重</span>
<span class="line">        auto iter = unique(nums.begin(), nums.end());</span>
<span class="line">        nums.erase(iter, nums.end());</span>
<span class="line"></span>
<span class="line">        // 保存结果</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">        // 某个元素使用 3 次得到 0 的只有 0 本身</span>
<span class="line">        if( record[0] &gt;= 3 ) {</span>
<span class="line">            res.push_back(vector&lt;int&gt;({0, 0, 0}));</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() &amp;&amp; nums[i] &lt;= 0 ; i++ ) {</span>
<span class="line">            for( int j = i+1 ; j &lt; nums.size() ; j++ ) {</span>
<span class="line"></span>
<span class="line">                // 1 nums[i] 使用两次的情况 &amp;&amp; nums[j] 使用一次的情况</span>
<span class="line">                if( record[nums[i]] &gt;= 2 &amp;&amp; 2 * nums[i] + nums[j] == 0 ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[i], nums[j]}));</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                // 2 nums[j] 使用两次的情况 &amp;&amp; nums[i] 使用一次的情况</span>
<span class="line">                if( record[nums[j]] &gt;= 2 &amp;&amp; 2 * nums[j] + nums[i] == 0 ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[j], nums[j]}));</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                // 3 nums[i] 和 nums[j] 只使用一次 剩余的一个元素从 nums[j] 的右侧寻找</span>
<span class="line">                int target = - ( nums[i] + nums[j] );</span>
<span class="line">                if( target &gt; nums[j] &amp;&amp; record.find(target) != record.end() ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[j], target}));</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>思路 2</strong></p>
<ul>
<li>遍历最左侧的元素 <code>nums[i]</code> 然后使用双指针的方法去寻找右边的两个元素，分别是 <code>nums[l]</code> 和 <code>nums[r]</code></li>
<li>会出现重复的情况有两种</li>
<li>第一种就是遍历 <code>nums[i]</code> 的时候，最左侧已经用过一次这个值了，下一次又用到了这个值，就会导致重复的情况出现，因为双指针寻找的是 <code>nums[i+1]</code> 右侧的值，寻找的内容还是相同的，所以肯定会造成重复</li>
<li>第二种重复的情况是在双指针寻找的过程中，当我们寻找到一个成功的组合后，我们应该让 <code>l</code> 和 <code>r</code> 都向内靠拢一次，也就是 <code>l++</code> 和 <code>r--</code> 一次，但是有一种可能就是 <code>nums[l+1]</code> 的值等于 <code>nums[l]</code> 并且 <code>nums[r-1]</code> 的值等于 <code>nums[r]</code> ，这时候 <code>nums[i]</code> 没有变，那么势必也会造成重复的组合出现</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;int&gt;&gt; threeSum(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        // 排序</span>
<span class="line">        sort(nums.begin(), nums.end());</span>
<span class="line"></span>
<span class="line">        // 保存结果</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            // 防止 0 0 0 1 2 3 4 5 这种情况的去重 此时 i 指向最左侧的 0</span>
<span class="line">            if( i &gt; 0 &amp;&amp; nums[i] == nums[i-1] ) continue;</span>
<span class="line"></span>
<span class="line">            int l = i+1;</span>
<span class="line">            int r = nums.size() - 1;</span>
<span class="line"></span>
<span class="line">            while( l &lt; r ) {</span>
<span class="line">                int target = - nums[i];</span>
<span class="line">                if( nums[l] + nums[r] == target ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[l], nums[r]}));</span>
<span class="line">                    // 防止 -1 0 0 0 1 2 3 4 5 这种情况去重 此时 l 指向最左侧的 0</span>
<span class="line">                    // 双指针指向的下一个元素 不能再和当前的元素一致了</span>
<span class="line">                    while( l &lt; r &amp;&amp; nums[l+1] == nums[l] ) l++;</span>
<span class="line">                    while( l &lt; r &amp;&amp; nums[r-1] == nums[r] ) r--;</span>
<span class="line"></span>
<span class="line">                    // 发现下一个元素已经和当前元素不同的时候 更新 l 和 r</span>
<span class="line">                    l++;</span>
<span class="line">                    r--;</span>
<span class="line">                } else if( nums[l] + nums[r] &gt; target ) {</span>
<span class="line">                    r--;</span>
<span class="line">                } else {</span>
<span class="line">                    l++;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0016 最接近的三数之和</title>
      <link>https://blueberry-universe.cn/2025-01-23-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-23-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0016 最接近的三数之和</source>
      <description>0016 最接近的三数之和
你好啊，我是蓝莓，今天是每日一题的第 27 天。
题目清单：一起刷力扣
引用力扣题目：16 最接近的三数之和
题目描述
给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数，使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1：...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 27 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/3sum-closest/description/" target="_blank" rel="noopener noreferrer">16 最接近的三数之和</a></p>
<h2>题目描述</h2>
<p>给你一个长度为 <code>n</code> 的整数数组 <code>nums</code> 和 一个目标值 <code>target</code>。请你从 <code>nums</code> 中选出三个整数，使它们的和与 <code>target</code> 最接近。</p>
<p>返回这三个数的和。</p>
<p>假定每组输入只存在恰好一个解。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [-1,2,1,-4], target = 1</span>
<span class="line">输出：2</span>
<span class="line">解释：与 target 最接近的和是 2 (-1 + 2 + 1 = 2)。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [0,0,0], target = 1</span>
<span class="line">输出：0</span>
<span class="line">解释：与 target 最接近的和是 0（0 + 0 + 0 = 0）。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>3 &lt;= nums.length &lt;= 1000</code></li>
<li><code>-1000 &lt;= nums[i] &lt;= 1000</code></li>
<li><code>-104 &lt;= target &lt;= 104</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这仍然是一个数字和的问题，只是这一次并不是去寻找一个 <code>三元组</code> 并且使得三元组中的几个数值的和为 <code>target</code>，而是寻找一个接近 <code>target</code> 的值，所以我们没有办法使用 <code>哈希表</code> 来优化最内层的循环了，因为我们计算出的那个数值在哈希表中查找不到并不意味着不存在一个数值使得他们相加后接近于 <code>target</code>。</li>
<li>在使用对撞指针的过程中，我们是通过不断的逼近 <code>target</code> 从而来寻找一个值的。这就意味着，对撞指针不仅能够用来精确的寻找一个值，而且也能用来寻找一个 <code>接近</code> 的值。</li>
<li>在这个题目中，对撞指针是同时引用了两个值，所以原本的三层循环让我们变成了一个外层循环加上一层对撞指针的循环。因此时间复杂度可从 <code>O(N^3)</code> 优化为 <code>O(N^2)</code></li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int threeSumClosest(vector&lt;int&gt;&amp; nums, int target) {</span>
<span class="line">        // 对撞指针</span>
<span class="line"></span>
<span class="line">        // 排序</span>
<span class="line">        sort(nums.begin(), nums.end());</span>
<span class="line"></span>
<span class="line">        // 初始化 这是被搜索到的第一组值</span>
<span class="line">        int sum = nums[0] + nums[1] + nums[nums.size() - 1];</span>
<span class="line"></span>
<span class="line">        // 搜索</span>
<span class="line">        for( int k = 0 ; k &lt; nums.size() ; k++ ) {</span>
<span class="line"></span>
<span class="line">            // 对撞指针搜索 nums[k+1...nums.size()-1]</span>
<span class="line">            // 从而不断的趋近 target 寻找最接近的值</span>
<span class="line">            int i = k+1;</span>
<span class="line">            int j = nums.size() - 1;</span>
<span class="line"></span>
<span class="line">            while( i &lt; j ) {</span>
<span class="line">                int temp = nums[k] + nums[i] + nums[j];</span>
<span class="line">                if( abs(temp - target) &lt; abs(sum - target) ) {</span>
<span class="line">                    sum = temp;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( temp &gt; target ) {</span>
<span class="line">                    j--;</span>
<span class="line">                } else {</span>
<span class="line">                    // temp &lt; target</span>
<span class="line">                    i++;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return sum;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0454 四数相加 II</title>
      <link>https://blueberry-universe.cn/2025-01-24-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0454 四数相加 II</source>
      <description>0454 四数相加 II
你好啊，我是蓝莓，今天是每日一题的第 28 天。
题目清单：一起刷力扣
引用力扣题目：454 四数相加 II
题目描述
给你四个整数数组 nums1、nums2、nums3 和 nums4 ，数组长度都是 n ，请你计算有多少个元组 (i, j, k, l) 能满足：

0 &amp;lt;= i, j, k, l &amp;lt; n
nu...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 28 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/4sum-ii/description/" target="_blank" rel="noopener noreferrer">454 四数相加 II</a></p>
<h2>题目描述</h2>
<p>给你四个整数数组 <code>nums1</code>、<code>nums2</code>、<code>nums3</code> 和 <code>nums4</code> ，数组长度都是 <code>n</code> ，请你计算有多少个元组 <code>(i, j, k, l)</code> 能满足：</p>
<ul>
<li><code>0 &lt;= i, j, k, l &lt; n</code></li>
<li><code>nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0</code></li>
</ul>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]</span>
<span class="line">输出：2</span>
<span class="line">解释：</span>
<span class="line">两个元组如下：</span>
<span class="line">1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0</span>
<span class="line">2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]</span>
<span class="line">输出：1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>n == nums1.length</code></li>
<li><code>n == nums2.length</code></li>
<li><code>n == nums3.length</code></li>
<li><code>n == nums4.length</code></li>
<li><code>1 &lt;= n &lt;= 200</code></li>
<li><code>-228 &lt;= nums1[i], nums2[i], nums3[i], nums4[i] &lt;= 228</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个情况，我们依然可以使用查找表对暴力方法进行优化</li>
<li>在以往的解题过程中，我们都是使用查找表对最内层的循环进行优化</li>
<li>对于四个数值的组合而言，优化后可以从 <code>O(N^4)</code> 降低到 <code>O(N^3)</code> 这个复杂度</li>
<li>其实我们还有更好的查找表使用技巧</li>
<li>我们可以先遍历 两两成对 的情况</li>
<li>（1）对 <code>nums1</code> 和 <code>nums2</code> 的数值组合成包含两个元素的元组和</li>
<li>（2）对 <code>nums3</code> 和 <code>nums4</code> 的数值组合成包含两个元素的元组和</li>
<li>（3）最后我们对所有的包含两个元组的元组和进行组合，组合成包含 4 个元素的元组和</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int fourSumCount(vector&lt;int&gt;&amp; nums1, vector&lt;int&gt;&amp; nums2, vector&lt;int&gt;&amp; nums3, vector&lt;int&gt;&amp; nums4) {</span>
<span class="line">        unsigned int n = nums1.size();</span>
<span class="line"></span>
<span class="line">        unordered_map&lt;int, int&gt; record1;</span>
<span class="line">        unordered_map&lt;int, int&gt; record2;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; n ; i++ ) {</span>
<span class="line">            for( int j = 0 ; j &lt; n ; j++ ) {</span>
<span class="line">                record1[nums1[i] + nums2[j]] += 1;</span>
<span class="line">                record2[nums3[i] + nums4[j]] += 1;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int counter = 0;</span>
<span class="line"></span>
<span class="line">        for( auto iter = record1.begin() ; iter != record1.end() ; iter++ ) {</span>
<span class="line">            int k1 = iter-&gt;first;</span>
<span class="line">            int v1 = iter-&gt;second;</span>
<span class="line"></span>
<span class="line">            int k2 = -k1;</span>
<span class="line">            if( record2.find(k2) != record2.end() ) {</span>
<span class="line">                int v2 = record2[k2];</span>
<span class="line">                counter += v1 * v2;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return counter;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0018 四数之和</title>
      <link>https://blueberry-universe.cn/2025-01-18-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-18-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0018 四数之和</source>
      <description>0018 四数之和
你好啊，我是蓝莓，今天是每日一题的第 26 天。
题目清单：一起刷力扣
引用力扣题目：18 四数之和
题目描述
给你一个由 n 个整数组成的数组 nums ，和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] （若两个四元组元素一一对...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 26 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/4sum/description/" target="_blank" rel="noopener noreferrer">18 四数之和</a></p>
<h2>题目描述</h2>
<p>给你一个由 <code>n</code> 个整数组成的数组 <code>nums</code> ，和一个目标值 <code>target</code> 。请你找出并返回满足下述全部条件且<strong>不重复</strong>的四元组 <code>[nums[a], nums[b], nums[c], nums[d]]</code> （若两个四元组元素一一对应，则认为两个四元组重复）：</p>
<ul>
<li><code>0 &lt;= a, b, c, d &lt; n</code></li>
<li><code>a</code>、<code>b</code>、<code>c</code> 和 <code>d</code> <strong>互不相同</strong></li>
<li><code>nums[a] + nums[b] + nums[c] + nums[d] == target</code></li>
</ul>
<p>你可以按 <strong>任意顺序</strong> 返回答案 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,0,-1,0,-2,2], target = 0</span>
<span class="line">输出：[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [2,2,2,2,2], target = 8</span>
<span class="line">输出：[[2,2,2,2]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 200</code></li>
<li><code>-109 &lt;= nums[i] &lt;= 109</code></li>
<li><code>-109 &lt;= target &lt;= 109</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目同样可以使用查找表优化</li>
<li>需要注意的是，由于这个需要使用四个数值组成一个 <code>四元组</code> 所以情况相对复杂一些</li>
<li>由于每个数值出现在 <code>nums</code> 数组中的次数可以有多次，所以组成四元组的方式主要有 4 种</li>
<li>（1）四元组中有一个互不相同的数值，并且满足要求的；</li>
<li>（2）四元组中有两个互不相同的数值，并且满足要求的；</li>
<li>（3）四元组中有三个互不相同的数值，并且满足要求的；</li>
<li>（4）四元组中有四个互不相同的数值，并且满足要求的；</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;int&gt;&gt; fourSum(vector&lt;int&gt;&amp; nums, int target) {</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line"></span>
<span class="line">        // 统计每个数值出现的次数</span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            record[nums[i]]++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 排序</span>
<span class="line">        sort(nums.begin(), nums.end());</span>
<span class="line"></span>
<span class="line">        // 去重</span>
<span class="line">        auto iter = unique(nums.begin(), nums.end());</span>
<span class="line">        nums.erase(iter, nums.end());</span>
<span class="line"></span>
<span class="line">        // 保存结果</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            // 只有一个不同数字的情况</span>
<span class="line">            if( record[nums[i]] &gt;= 4 &amp;&amp; 4 * (long long)nums[i] == target ) {</span>
<span class="line">                res.push_back(vector&lt;int&gt;({nums[i], nums[i], nums[i], nums[i]}));</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            for( int j = i+1 ; j &lt; nums.size() ; j++ ) {</span>
<span class="line">                // 两个不同数字的情况</span>
<span class="line">                if( record[nums[i]] &gt;= 3 &amp;&amp; 3 * (long long)nums[i] + (long long)nums[j] == target ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[i], nums[i], nums[j]}));</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( record[nums[j]] &gt;= 3 &amp;&amp; (long long)nums[i] + 3 * (long long)nums[j] == target ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[j], nums[j], nums[j]}));</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( record[nums[i]] &gt;= 2 &amp;&amp; record[nums[j]] &gt;= 2 &amp;&amp; 2 * (long long)nums[i] + 2 * (long long)nums[j] == target ) {</span>
<span class="line">                    res.push_back(vector&lt;int&gt;({nums[i], nums[i], nums[j], nums[j]}));</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                for( int k = j+1 ; k &lt; nums.size() ; k++ ) {</span>
<span class="line">                    // 3 个不同数字的情况</span>
<span class="line">                    if( record[nums[i]] &gt;= 2 &amp;&amp; 2 * (long long)nums[i] + (long long)nums[j] + (long long)nums[k] == target ) {</span>
<span class="line">                        res.push_back(vector&lt;int&gt;({nums[i], nums[i], nums[j], nums[k]}));</span>
<span class="line">                    }</span>
<span class="line"></span>
<span class="line">                    if( record[nums[j]] &gt;= 2 &amp;&amp; (long long)nums[i] + 2 * (long long)nums[j] + (long long)nums[k] == target ) {</span>
<span class="line">                        res.push_back(vector&lt;int&gt;({nums[i], nums[j], nums[j], nums[k]}));</span>
<span class="line">                    }</span>
<span class="line"></span>
<span class="line">                    if( record[nums[k]] &gt;= 2 &amp;&amp; (long long)nums[i] + (long long)nums[j] + 2 * (long long)nums[k] == target ) {</span>
<span class="line">                        res.push_back(vector&lt;int&gt;({nums[i], nums[j], nums[k], nums[k]}));</span>
<span class="line">                    }</span>
<span class="line"></span>
<span class="line">                    // 4 个不同数字的情况 使用哈希表优化一层循环</span>
<span class="line">                    int num = target - (long long)(nums[i] + nums[j] + nums[k]);</span>
<span class="line">                    if( record.find(num) != record.end() &amp;&amp; num &gt; nums[k] ) {</span>
<span class="line">                        res.push_back(vector&lt;int&gt;({nums[i], nums[j], nums[k], num}));</span>
<span class="line">                    }</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        } </span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0049 字母异位词分组</title>
      <link>https://blueberry-universe.cn/2025-01-24-01/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0049 字母异位词分组</source>
      <description>0049 字母异位词分组
你好啊，我是蓝莓，今天是每日一题的第 29 天。
题目清单：一起刷力扣
引用力扣题目：49 字母异位词分组
题目描述
给你一个字符串数组，请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
示例 1:

示例 2:

示例 3:

提示：

1 &amp;lt;= ...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 29 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/group-anagrams/description/" target="_blank" rel="noopener noreferrer">49 字母异位词分组</a></p>
<h2>题目描述</h2>
<p>给你一个字符串数组，请你将 <strong>字母异位词</strong> 组合在一起。可以按任意顺序返回结果列表。</p>
<p><strong>字母异位词</strong> 是由重新排列源单词的所有字母得到的一个新单词。</p>
<p><strong>示例 1:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]</span>
<span class="line">输出: [["bat"],["nat","tan"],["ate","eat","tea"]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: strs = [""]</span>
<span class="line">输出: [[""]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3:</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: strs = ["a"]</span>
<span class="line">输出: [["a"]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= strs.length &lt;= 104</code></li>
<li><code>0 &lt;= strs[i].length &lt;= 100</code></li>
<li><code>strs[i]</code> 仅包含小写字母</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>我们需要对每一个单词进行归类</li>
<li>归类的标准是这个单词用到的字母所属的集合是相同的；其实这个说法还是不太严谨，因为如果同时出现了两个相同的字母，我们是不能去重的；</li>
<li>所以呢，我们可以对每个单词的字母按照字典序进行排序，如果排序后展现出来的是同样的内容，那么它们就是同一个类别的</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;string&gt;&gt; groupAnagrams(vector&lt;string&gt;&amp; strs) {</span>
<span class="line">        unordered_map&lt;string, vector&lt;string&gt;&gt; record;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; strs.size() ; i++ ) {</span>
<span class="line">            string s = strs[i];</span>
<span class="line">            sort(s.begin(), s.end());</span>
<span class="line">            record[s].push_back(strs[i]);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        vector&lt;vector&lt;string&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">        for( auto iter = record.begin() ; iter != record.end() ; iter++ ) {</span>
<span class="line">            res.push_back(iter-&gt;second);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0447 回旋镖的数量</title>
      <link>https://blueberry-universe.cn/2025-01-24-02/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-02/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0447 回旋镖的数量</source>
      <description>0447 回旋镖的数量
你好啊，我是蓝莓，今天是每日一题的第 30 天。
题目清单：一起刷力扣
引用力扣题目：447 回旋镖的数量
题目描述
给定平面上 n 对 互不相同 的点 points ，其中 points[i] = [xi, yi] 。回旋镖 是由点 (i, j, k) 表示的元组 ，其中 i 和 j 之间的欧式距离和 i 和 k 之间的欧式距...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 30 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/number-of-boomerangs/description/" target="_blank" rel="noopener noreferrer">447 回旋镖的数量</a></p>
<h2>题目描述</h2>
<p>给定平面上 <code>n</code> 对 <strong>互不相同</strong> 的点 <code>points</code> ，其中 <code>points[i] = [xi, yi]</code> 。<strong>回旋镖</strong> 是由点 <code>(i, j, k)</code> 表示的元组 ，其中 <code>i</code> 和 <code>j</code> 之间的欧式距离和 <code>i</code> 和 <code>k</code> 之间的欧式距离相等（<strong>需要考虑元组的顺序</strong>）。</p>
<p>返回平面上所有回旋镖的数量。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：points = [[0,0],[1,0],[2,0]]</span>
<span class="line">输出：2</span>
<span class="line">解释：两个回旋镖为 [[1,0],[0,0],[2,0]] 和 [[1,0],[2,0],[0,0]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：points = [[1,1],[2,2],[3,3]]</span>
<span class="line">输出：2</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：points = [[1,1]]</span>
<span class="line">输出：0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>n == points.length</code></li>
<li><code>1 &lt;= n &lt;= 500</code></li>
<li><code>points[i].length == 2</code></li>
<li><code>-104 &lt;= xi, yi &lt;= 104</code></li>
<li>所有点都 <strong>互不相同</strong></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>在这里要考虑的是对于每一个三元组中的点 <code>point[i]</code> 来说，只要我们计算出所有其它的点到这个点的距离然后按照距离对其他所有的点进行归类就可以</li>
<li>归类后，我们通过遍历所有不同的距离中收集到的不同的点，我们计算一下，这些点使用排列的方式放在 <code>j</code> 和 <code>k</code> 的位置有多少种排列的方式</li>
<li>如果某类距离中收集到的点的数量为 <code>k</code> 那么根据排列的计算方法，我们可以知道有 <code>k * (k-1)</code> 中摆放方法</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int numberOfBoomerangs(vector&lt;vector&lt;int&gt;&gt;&amp; points) {</span>
<span class="line">        // 对于每一个点 point[i]</span>
<span class="line">        // 计算出其它所有的点到这个点的欧拉距离为 dist 的顶点数量</span>
<span class="line">        vector&lt;unordered_map&lt;int, int&gt;&gt; record(points.size());</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; points.size() ; i++ ) {</span>
<span class="line">            for( int j = 0 ; j &lt; points.size() ; j++ ) {</span>
<span class="line">                int dist = distance(points[i], points[j]);</span>
<span class="line">                record[i][dist]++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int counter = 0;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; points.size() ; i++ ) {</span>
<span class="line">            for( auto iter = record[i].begin() ; iter != record[i].end() ; iter++ ) {</span>
<span class="line">                int k = iter-&gt;second;</span>
<span class="line">                counter += k * (k-1);</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return counter;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    int inline distance(vector&lt;int&gt;&amp; p1, vector&lt;int&gt;&amp; p2) {</span>
<span class="line">        int a = p1[0] - p2[0];</span>
<span class="line">        int b = p1[1] - p2[1];</span>
<span class="line">        return a * a + b * b;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0149 直线上最多的点数</title>
      <link>https://blueberry-universe.cn/2025-01-24-03/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-03/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0149 直线上最多的点数</source>
      <description>0149 直线上最多的点数
你好啊，我是蓝莓，今天是每日一题的第 31 天。
题目清单：一起刷力扣
引用力扣题目：149 直线上最多的点数
题目描述
给你一个数组 points ，其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
示例 1：
img

示例 2：
img

提示：

1 &amp;l...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 31 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/max-points-on-a-line/description/" target="_blank" rel="noopener noreferrer">149 直线上最多的点数</a></p>
<h2>题目描述</h2>
<p>给你一个数组 <code>points</code> ，其中 <code>points[i] = [xi, yi]</code> 表示 <strong>X-Y</strong> 平面上的一个点。求最多有多少个点在同一条直线上。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：points = [[1,1],[2,2],[3,3]]</span>
<span class="line">输出：3</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2021/02/25/plane2.jpg" alt="img"></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]</span>
<span class="line">输出：4</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= points.length &lt;= 300</code></li>
<li><code>points[i].length == 2</code></li>
<li><code>-10^4 &lt;= xi, yi &lt;= 10^4</code></li>
<li><code>points</code> 中的所有点 <strong>互不相同</strong></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>我们都知道两点确定一条直线</li>
<li>先确定一个点，然后求该点和其他所有点构成直线的斜率，使用求得的斜率作为哈希表的 <code>key</code> ，使用落在该斜率上的点的数量作为哈希表的值</li>
<li>现在最大的问题是，斜率是一个小数，但是在计算机中只有浮点数，所以是有误差的，不太能作为哈希表的键</li>
<li>另一种斜率表示法：我们可以使用比值的方式存储斜率，只需要将该分数的分子和分母化为最简就可以了，这样一来，我们就可以使用两个整型精确的表示一个分数了</li>
<li>设 <code>a</code> 为该分数的分子，<code>b</code>为该分数的分母，为了统一，若该分数为负数，我们总是让负号出现在 <code>b</code> 中</li>
<li>根据题目提供的信息我们可以知道</li>
<li>（1）表示斜率的分子被我们统一成了整数，结合每个点的坐标范围，我们可以计算出斜率的分子 <code>a</code> 的范围是 <code>0 到 2 × 10^4</code></li>
<li>（2）表示斜率的分母 <code>b</code> 可正可负，所以分母的取值范围是 <code>-2 × 10^4 到 2 × 10^4</code></li>
<li>最后，我们使用一个 32 位的整数来保存这两个内容，我们让 <code>b</code> 乘以 <code>2 × 10^4 + 1</code> 这样一来，我们就在数轴的中间部分空出了很大一部分的空间，我们让这个数值再加上 <code>a</code> ，这样一来，我们总是可以通过两个值的和得到唯一的 键</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line"></span>
<span class="line">    int _gcd(int a, int b) {</span>
<span class="line">        if( b == 0 ) {</span>
<span class="line">            return a;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return _gcd(b, a%b);</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    int gcd(int a, int b) {</span>
<span class="line">        if( a == b ) {</span>
<span class="line">            return a;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return _gcd(max(a, b), min(a, b));</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    int maxPoints(vector&lt;vector&lt;int&gt;&gt;&amp; points) {</span>
<span class="line">        // 对每一个点 i;</span>
<span class="line">        // record[i] 记录其他点到该点不同斜率收集的点的数量</span>
<span class="line">        // record[i][斜率] = 数量</span>
<span class="line">        int res = 0;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; points.size() ; i++ ) {</span>
<span class="line"></span>
<span class="line">            unordered_map&lt;int, int&gt; record; </span>
<span class="line">            for( int j = 0 ; j &lt; points.size() ; j++ ) {</span>
<span class="line">                if( i == j ) continue;</span>
<span class="line"></span>
<span class="line">                int a = points[i][0] - points[j][0];</span>
<span class="line">                int b = points[i][1] - points[j][1];</span>
<span class="line"></span>
<span class="line">                if( a == 0 ) {</span>
<span class="line">                    b = 1;</span>
<span class="line">                } else if( b == 0 ) {</span>
<span class="line">                    a = 1;</span>
<span class="line">                } else {</span>
<span class="line">                    </span>
<span class="line">                    if( a &lt; 0 ) {</span>
<span class="line">                        a = -a;</span>
<span class="line">                        b = -b;</span>
<span class="line">                    }</span>
<span class="line">                    int ab_gcd = gcd(abs(a), abs(b));</span>
<span class="line"></span>
<span class="line">                    a = a / ab_gcd;</span>
<span class="line">                    b = b / ab_gcd;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                // 从数轴上可以观察到这样不会产生冲突</span>
<span class="line">                int key = 20001 * b + a;</span>
<span class="line">                record[key] ++;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            for( auto iter = record.begin() ; iter != record.end() ; iter++ ) {</span>
<span class="line">                res = max(res, iter-&gt;second);</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res+1;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0219 存在重复元素 II</title>
      <link>https://blueberry-universe.cn/2025-01-24-04/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-04/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0219 存在重复元素 II</source>
      <description>0219 存在重复元素 II
你好啊，我是蓝莓，今天是每日一题的第 32 天。
题目清单：一起刷力扣
引用力扣题目：219 存在重复元素 II
题目描述
给你一个整数数组 nums 和一个整数 k ，判断数组中是否存在两个 不同的索引 i 和 j ，满足 nums[i] == nums[j] 且 abs(i - j) &amp;lt;= k 。如果存在，返回 ...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 32 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/contains-duplicate-ii/description/" target="_blank" rel="noopener noreferrer">219 存在重复元素 II</a></p>
<h2>题目描述</h2>
<p>给你一个整数数组 <code>nums</code> 和一个整数 <code>k</code> ，判断数组中是否存在两个 <strong>不同的索引</strong> <code>i</code> 和 <code>j</code> ，满足 <code>nums[i] == nums[j]</code> 且 <code>abs(i - j) &lt;= k</code> 。如果存在，返回 <code>true</code> ；否则，返回 <code>false</code> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,2,3,1], k = 3</span>
<span class="line">输出：true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,0,1,1], k = 1</span>
<span class="line">输出：true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,2,3,1,2,3], k = 2</span>
<span class="line">输出：false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 105</code></li>
<li><code>-109 &lt;= nums[i] &lt;= 109</code></li>
<li><code>0 &lt;= k &lt;= 105</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>题目要求寻找两个重复的元素，并且这两个元素之间的距离不超过 <code>k</code></li>
<li>我们可以维护一个滑动窗口，使用哈希表记录这个滑动窗口内的每个元素出现的次数</li>
<li>如果当前没有出现重复的元素，那么就向右滑动一下，扔掉旧的元素，纳入新的元素，并检查纳入新的元素后是否出现了重复的元素</li>
<li>这时候，如果出现了重复元素就可以直接返回成功了</li>
<li>如果没有出现，那就需要继续滑动窗口</li>
<li>如果所有的元素都扫过了一遍还是没成功，那肯定就是失败了</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool containsNearbyDuplicate(vector&lt;int&gt;&amp; nums, int k) {</span>
<span class="line">        </span>
<span class="line">        int l = 0;</span>
<span class="line">        int r = k &lt; nums.size() - 1 ? k : nums.size() - 1;</span>
<span class="line"></span>
<span class="line">        // num -&gt; freq </span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line">        </span>
<span class="line">        for( int i = 0 ; i &lt;= r ; i++ ) {</span>
<span class="line">            if(++record[nums[i]] &gt;= 2) {</span>
<span class="line">                return true;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = r+1 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            // 扔掉以前的元素</span>
<span class="line">            record[nums[l++]]--;</span>
<span class="line">            </span>
<span class="line">            // 加入新的元素</span>
<span class="line">            if(++record[nums[i]] &gt;= 2) {</span>
<span class="line">                return true;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return false;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0219 存在重复元素 II</title>
      <link>https://blueberry-universe.cn/2025-01-24-05/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-05/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0219 存在重复元素 II</source>
      <description>0219 存在重复元素 II
你好啊，我是蓝莓，今天是每日一题的第 32 天。
题目清单：一起刷力扣
引用力扣题目：217 存在重复元素
题目描述
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ，返回 true ；如果数组中每个元素互不相同，返回 false 。
示例 1：
**输入：**nums = [1,2,3,1]
**输出：*...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 32 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/contains-duplicate/description/" target="_blank" rel="noopener noreferrer">217 存在重复元素</a></p>
<h2>题目描述</h2>
<p>给你一个整数数组 <code>nums</code> 。如果任一值在数组中出现 <strong>至少两次</strong> ，返回 <code>true</code> ；如果数组中每个元素互不相同，返回 <code>false</code> 。</p>
<p><strong>示例 1：</strong></p>
<p>**输入：**nums = [1,2,3,1]</p>
<p>**输出：**true</p>
<p><strong>解释：</strong></p>
<p>元素 1 在下标 0 和 3 出现。</p>
<p><strong>示例 2：</strong></p>
<p>**输入：**nums = [1,2,3,4]</p>
<p>**输出：**false</p>
<p><strong>解释：</strong></p>
<p>所有元素都不同。</p>
<p><strong>示例 3：</strong></p>
<p>**输入：**nums = [1,1,1,3,3,4,3,2,4,2]</p>
<p>**输出：**true</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= nums.length &lt;= 105</code></li>
<li><code>-109 &lt;= nums[i] &lt;= 109</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个简单题，直接使用哈希表来记录每个遍历过得元素出现的次数就可以</li>
<li>当我们将一个新的元素加入到哈希表的统计后，我们就看看当前这个元素的出现次数是不是大于或等于 2 了，如果是的话，直接返回成功，不然继续遍历</li>
<li>如果遍历完所有的元素后都没有成功，那就说明不存在重复的元素，返回失败</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool containsDuplicate(vector&lt;int&gt;&amp; nums) {</span>
<span class="line">        unordered_map&lt;int, int&gt; record;</span>
<span class="line"></span>
<span class="line">        for( int num : nums ) {</span>
<span class="line">            if( ++record[num] &gt;= 2 ) {</span>
<span class="line">                return true;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return false;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0220 存在重复元素 III</title>
      <link>https://blueberry-universe.cn/2025-01-24-06/</link>
      <guid>https://blueberry-universe.cn/2025-01-24-06/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0220 存在重复元素 III</source>
      <description>0220 存在重复元素 III
你好啊，我是蓝莓，今天是每日一题的第 32 天。
题目清单：一起刷力扣
引用力扣题目：220 存在重复元素 III
题目描述
给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。
找出满足下述条件的下标对 (i, j)：

i != j,
abs(i - j) &amp;lt;= indexDi...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 32 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/contains-duplicate-iii/description/" target="_blank" rel="noopener noreferrer">220 存在重复元素 III</a></p>
<h2>题目描述</h2>
<p>给你一个整数数组 <code>nums</code> 和两个整数 <code>indexDiff</code> 和 <code>valueDiff</code> 。</p>
<p>找出满足下述条件的下标对 <code>(i, j)</code>：</p>
<ul>
<li><code>i != j</code>,</li>
<li><code>abs(i - j) &lt;= indexDiff</code></li>
<li><code>abs(nums[i] - nums[j]) &lt;= valueDiff</code></li>
</ul>
<p>如果存在，返回 <code>true</code> *；*否则，返回 <code>false</code> 。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,2,3,1], indexDiff = 3, valueDiff = 0</span>
<span class="line">输出：true</span>
<span class="line">解释：可以找出 (i, j) = (0, 3) 。</span>
<span class="line">满足下述 3 个条件：</span>
<span class="line">i != j --> 0 != 3</span>
<span class="line">abs(i - j) &lt;= indexDiff --> abs(0 - 3) &lt;= 3</span>
<span class="line">abs(nums[i] - nums[j]) &lt;= valueDiff --> abs(1 - 1) &lt;= 0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：nums = [1,5,9,1,5,9], indexDiff = 2, valueDiff = 3</span>
<span class="line">输出：false</span>
<span class="line">解释：尝试所有可能的下标对 (i, j) ，均无法满足这 3 个条件，因此返回 false 。</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>2 &lt;= nums.length &lt;= 105</code></li>
<li><code>-109 &lt;= nums[i] &lt;= 109</code></li>
<li><code>1 &lt;= indexDiff &lt;= nums.length</code></li>
<li><code>0 &lt;= valueDiff &lt;= 109</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目设计到了二分搜索树的有序性，在 <code>C++</code> 中的 <code>set</code> 底层是使用红黑树实现的，而 <code>unordered_set</code> 的底层是使用哈希表实现的</li>
<li>所以，我们可以使用 <code>set</code>，一旦它维护的元素有了顺序之后，我们就可以针对某个数值 <code>key</code> 去更快的寻找最接近 <code>key</code> 且大于或等于 <code>key</code> 的那个数值</li>
<li>在 <code>C++</code> 中的 <code>set</code> 提供了 <code>lower_bound</code> 方法来来寻找大于等于 <code>key</code> 的数值</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool containsNearbyAlmostDuplicate(vector&lt;int&gt;&amp; nums, int indexDiff, int valueDiff) {</span>
<span class="line">        set&lt;int&gt; record;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; nums.size() ; i++ ) {</span>
<span class="line">            // 对于给定的 nums[i] 查找 record 中是否存在一个数组 num</span>
<span class="line">            // nums[i] - valueDiff &lt;= num &lt;= nums[i] + valueDiff</span>
<span class="line">            // 转换成寻找一个最接近 nums[i] - valueDiff 但是大于等于 nums[i] - valueDiff 的值</span>
<span class="line">            // 而且这个值小于等于 nums[i] + valueDiff</span>
<span class="line"></span>
<span class="line">            int key = nums[i] - valueDiff;</span>
<span class="line">            int upper = nums[i] + valueDiff;</span>
<span class="line">            if( record.lower_bound(key) != record.end() &amp;&amp; *record.lower_bound(key) &lt;= upper ) {</span>
<span class="line">                return true;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            record.insert( nums[i] );</span>
<span class="line">            // 因为 valueDiff 最小的数值为 0</span>
<span class="line">            // 如果 set 中存在了相同的元素</span>
<span class="line">            // 那么就一定会满足题意 所以只要算法还在进行</span>
<span class="line">            // 就说明一定没有向 set 添加过重复的元素</span>
<span class="line">            if( record.size() == indexDiff + 1 ) {</span>
<span class="line">                record.erase(nums[i-indexDiff]);</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return false;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0206 反转链表</title>
      <link>https://blueberry-universe.cn/2025-01-25-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-25-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0206 反转链表</source>
      <description>0206 反转链表
你好啊，我是蓝莓，今天是每日一题的第 33 天。
题目清单：一起刷力扣
引用力扣题目：206 反转链表
题目描述
给你单链表的头节点 head ，请你反转链表，并返回反转后的链表。
示例 1：
img

示例 2：
img

示例 3：

提示：

链表中节点的数目范围是 [0, 5000]
-5000 &amp;lt;= Node.val...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 33 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/reverse-linked-list/description/" target="_blank" rel="noopener noreferrer">206 反转链表</a></p>
<h2>题目描述</h2>
<p>给你单链表的头节点 <code>head</code> ，请你反转链表，并返回反转后的链表。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4,5]</span>
<span class="line">输出：[5,4,3,2,1]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2]</span>
<span class="line">输出：[2,1]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点的数目范围是 <code>[0, 5000]</code></li>
<li><code>-5000 &lt;= Node.val &lt;= 5000</code></li>
</ul>
<p>**进阶：**链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个和链表相关的简单题</li>
<li>为了更容易的反转链表，我们引入一个虚拟头结点，这样能简化代码的逻辑，省掉很多的边界处理</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* reverseList(ListNode* head) {</span>
<span class="line">		//如果链表为空则直接返回 空</span>
<span class="line">        if( head == nullptr ) {</span>
<span class="line">            return head;</span>
<span class="line">        }</span>
<span class="line">		</span>
<span class="line">        // 创建一个虚拟头结点 让它的 next 指向真正的头结点 head</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line">		</span>
<span class="line">        // pre 表示当前遍历到的节点的前一个节点</span>
<span class="line">        ListNode* pre = dummyHead;</span>
<span class="line">        // cur 表示当前正要修改 next 指向的节点</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line">		</span>
<span class="line">        // 若 cur 已经为 nullptr 说明遍历结束</span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            // 记录 cur 指向的下一个节点</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line">			</span>
<span class="line">            // 让 cur 指向前一个节点 pre</span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            // 为下一轮循环做准备</span>
<span class="line">            // 分别将 pre 和 cur 向后移动一下</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line">		</span>
<span class="line">        // 其实这个时候 整个链表的翻转已经结束了</span>
<span class="line">        // 但是 最一开始的 head 节点已经成为了尾节点</span>
<span class="line">        // 它应该指向 nullptr 才对</span>
<span class="line">        // 恰巧我们记得 dummyHead 是指向最开始的 head 节点的</span>
<span class="line">        // 我们通过它来修改 head 的 next 的指向</span>
<span class="line">        // 当然你也可以直接通过 head 来修改</span>
<span class="line">        dummyHead-&gt;next-&gt;next = nullptr;</span>
<span class="line">		</span>
<span class="line">        // 此时的 pre 正好就是翻转链表后的头结点</span>
<span class="line">        return pre;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0092 反转链表 II</title>
      <link>https://blueberry-universe.cn/2025-01-25-01/</link>
      <guid>https://blueberry-universe.cn/2025-01-25-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0092 反转链表 II</source>
      <description>0092 反转链表 II
你好啊，我是蓝莓，今天是每日一题的第 34 天。
题目清单：一起刷力扣
引用力扣题目：92 反转链表 II
题目描述
给你单链表的头指针 head 和两个整数 left 和 right ，其中 left &amp;lt;= right 。请你反转从位置 left 到位置 right 的链表节点，返回 反转后的链表 。
示例 1：
im...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 34 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/reverse-linked-list-ii/description/" target="_blank" rel="noopener noreferrer">92 反转链表 II</a></p>
<h2>题目描述</h2>
<p>给你单链表的头指针 <code>head</code> 和两个整数 <code>left</code> 和 <code>right</code> ，其中 <code>left &lt;= right</code> 。请你反转从位置 <code>left</code> 到位置 <code>right</code> 的链表节点，返回 <strong>反转后的链表</strong> 。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4,5], left = 2, right = 4</span>
<span class="line">输出：[1,4,3,2,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [5], left = 1, right = 1</span>
<span class="line">输出：[5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点数目为 <code>n</code></li>
<li><code>1 &lt;= n &lt;= 500</code></li>
<li><code>-500 &lt;= Node.val &lt;= 500</code></li>
<li><code>1 &lt;= left &lt;= right &lt;= n</code></li>
</ul>
<p><strong>进阶：</strong> 你可以使用一趟扫描完成反转吗？</p>
<h2>实现</h2>
<p><strong>思路 1</strong></p>
<ul>
<li>比较简单的思路是，我们先遍历一遍链表来寻找几个关键的节点</li>
<li>然后再对中间部分的链表进行翻转，随后调整关键位置的指向</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* reverseBetween(ListNode* head, int left, int right) {</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        // 找到 left 和 right 代表的节点</span>
<span class="line">        ListNode* leftPre = nullptr;  // left 的前一个节点</span>
<span class="line">        ListNode* leftNode = nullptr;  // left 节点</span>
<span class="line">        ListNode* rightNode = nullptr;  // right 节点</span>
<span class="line">        ListNode* rightNext = nullptr;  // right 后一个节点</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummyHead;  // 遍历过程中的前一个节点</span>
<span class="line">        ListNode* cur = head;  // 遍历过程中的后一个节点</span>
<span class="line"></span>
<span class="line">        // 寻找节点</span>
<span class="line">        int counter = 1;</span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            if( counter == left ) {</span>
<span class="line">                leftPre = pre;</span>
<span class="line">                leftNode = cur;</span>
<span class="line">            }</span>
<span class="line">            </span>
<span class="line">            if( counter == right ) {</span>
<span class="line">                rightNode = cur;</span>
<span class="line">                rightNext = cur-&gt;next;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = cur-&gt;next;</span>
<span class="line">            counter++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        cur = leftNode;</span>
<span class="line">        pre = leftPre;</span>
<span class="line">        // 翻转链表</span>
<span class="line">        while( cur != rightNext ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line"></span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 调整翻转后的中间部分的链表指向关系</span>
<span class="line">        leftNode-&gt;next = rightNext;</span>
<span class="line">        leftPre-&gt;next = rightNode;</span>
<span class="line"></span>
<span class="line">        return dummyHead-&gt;next;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>思路 2</strong></p>
<ul>
<li>在第一种方法中，我们遍历了两次链表才把问题解决</li>
<li>其实核心问题是要确定，在什么范围内才翻转链表？</li>
<li>根据题目描述，我们要在给定的范围内才需要对链表进行翻转</li>
<li>那就是这样的一个范围 <code>counter &gt;= left &amp;&amp; counter &lt;= right</code>； 其中 <code>counter</code> 代表当前是第几个节点</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* reverseBetween(ListNode* head, int left, int right) {</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        // 找到 left 和 right 代表的节点</span>
<span class="line">        ListNode* leftPre = nullptr;  // left 的前一个节点</span>
<span class="line">        ListNode* leftNode = nullptr;  // left 节点</span>
<span class="line">        ListNode* rightNode = nullptr;  // right 节点</span>
<span class="line">        ListNode* rightNext = nullptr;  // right 后一个节点</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummyHead;  // 遍历过程中的前一个节点</span>
<span class="line">        ListNode* cur = head;  // 遍历过程中的后一个节点</span>
<span class="line"></span>
<span class="line">        int counter = 1;</span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line"></span>
<span class="line">            if( counter == left ) {</span>
<span class="line">                leftPre = pre;</span>
<span class="line">                leftNode = cur;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            if( counter == right ) {</span>
<span class="line">                rightNode = cur;</span>
<span class="line">                rightNext = next;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 如果在给定范围内 那就翻转链表</span>
<span class="line">            if( counter &gt;= left &amp;&amp; counter &lt;= right ) {</span>
<span class="line">                cur-&gt;next = pre;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 移动到下一个节点</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">            counter++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 调整指针的指向</span>
<span class="line">        leftPre-&gt;next = rightNode;</span>
<span class="line">        leftNode-&gt;next = rightNext;</span>
<span class="line">        </span>
<span class="line">        return dummyHead-&gt;next;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0083 删除排序链表中的重复元素</title>
      <link>https://blueberry-universe.cn/2025-01-26-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-26-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0083 删除排序链表中的重复元素</source>
      <description>0083 删除排序链表中的重复元素
你好啊，我是蓝莓，今天是每日一题的第 35 天。
题目清单：一起刷力扣
引用力扣题目：83 删除排序链表中的重复元素
题目描述
给定一个已排序的链表的头 head ， 删除所有重复的元素，使每个元素只出现一次 。返回 已排序的链表 。
示例 1：
img

示例 2：
img

提示：

链表中节点数目在范围 [0,...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 35 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/remove-duplicates-from-sorted-list/description/" target="_blank" rel="noopener noreferrer">83 删除排序链表中的重复元素</a></p>
<h2>题目描述</h2>
<p>给定一个已排序的链表的头 <code>head</code> ， <em>删除所有重复的元素，使每个元素只出现一次</em> 。返回 <em>已排序的链表</em> 。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,1,2]</span>
<span class="line">输出：[1,2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,1,2,3,3]</span>
<span class="line">输出：[1,2,3]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点数目在范围 <code>[0, 300]</code> 内</li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
<li>题目数据保证链表已经按升序 <strong>排列</strong></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>题目已经保证了链表中存储的元素是按照升序排列的</li>
<li>（1）使用 <code>pre</code> 指向当前遍历的节点的前一个</li>
<li>（2）使用 <code>cur</code> 只想当前正在遍历的节点，如果 <code>cur</code> 节点的值和 <code>pre</code> 节点的值是一样的，那么就从链表中删除 <code>cur</code> 节点，并修改 <code>pre</code> 节点的 <code>next</code> 指针，否则说明当前节点是不重复的</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* deleteDuplicates(ListNode* head) {</span>
<span class="line"></span>
<span class="line">        if( head == nullptr ) {</span>
<span class="line">            return head;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* pre = head;</span>
<span class="line">        ListNode* cur = head-&gt;next;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            if( pre-&gt;val == cur-&gt;val ) {</span>
<span class="line">                pre-&gt;next = cur-&gt;next;</span>
<span class="line">                cur = pre-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                pre = cur;</span>
<span class="line">                cur = cur-&gt;next;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return head;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0086 分隔链表</title>
      <link>https://blueberry-universe.cn/2025-01-27-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-27-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0086 分隔链表</source>
      <description>0086 分隔链表
你好啊，我是蓝莓，今天是每日一题的第 36 天。
题目清单：一起刷力扣
引用力扣题目：86 分割链表
题目描述
给你一个链表的头节点 head 和一个特定值 x ，请你对链表进行分隔，使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
示例 1：
img

示例 2：
...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 36 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/partition-list/description/" target="_blank" rel="noopener noreferrer">86 分割链表</a></p>
<h2>题目描述</h2>
<p>给你一个链表的头节点 <code>head</code> 和一个特定值 <code>x</code> ，请你对链表进行分隔，使得所有 <strong>小于</strong> <code>x</code> 的节点都出现在 <strong>大于或等于</strong> <code>x</code> 的节点之前。</p>
<p>你应当 <strong>保留</strong> 两个分区中每个节点的初始相对位置。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,4,3,2,5,2], x = 3</span>
<span class="line">输出：[1,2,2,4,3,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [2,1], x = 2</span>
<span class="line">输出：[1,2]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点的数目在范围 <code>[0, 200]</code> 内</li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
<li><code>-200 &lt;= x &lt;= 200</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>题目要求的我们将链表分割成两部分</li>
<li>（1）比 x 小的部分</li>
<li>（2）比 x 大或者等于的部分</li>
<li>对于这两个部分，我们可以新建两个虚拟头结点，然后遍历原始链表，每次遍历到的节点都将它从原始链表上摘下来放在对应分类的虚拟头结点所在的链表尾部，最后将两个新的链表进行合并即可</li>
<li>这样一来，不仅可以在一轮遍历中完成链表分割，而且保持了元素的相对顺序</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* partition(ListNode* head, int x) {</span>
<span class="line"></span>
<span class="line">        if( head == nullptr ) {</span>
<span class="line">            return head;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* lessHead = new ListNode(-1, nullptr);</span>
<span class="line">        ListNode* greatHead = new ListNode(-1, nullptr);</span>
<span class="line"></span>
<span class="line">        ListNode* lessCur = lessHead;</span>
<span class="line">        ListNode* greatCur = greatHead;</span>
<span class="line"></span>
<span class="line">        ListNode* cur = head;</span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line"></span>
<span class="line">            if( cur-&gt;val &gt;= x ) {</span>
<span class="line">                greatCur-&gt;next = cur;</span>
<span class="line">                greatCur = cur;</span>
<span class="line">            } else {</span>
<span class="line">                // cur-&gt;val &lt; x</span>
<span class="line">                lessCur-&gt;next = cur;</span>
<span class="line">                lessCur = cur;</span>
<span class="line">            }</span>
<span class="line">            </span>
<span class="line">            cur-&gt;next = nullptr;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* res = nullptr;</span>
<span class="line"></span>
<span class="line">        if( lessHead-&gt;next != nullptr ) {</span>
<span class="line">            res = lessHead-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( res != nullptr ) {</span>
<span class="line">            lessCur-&gt;next = greatHead-&gt;next;</span>
<span class="line">        } else {</span>
<span class="line">            res = greatHead-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0328 奇偶链表</title>
      <link>https://blueberry-universe.cn/2025-01-27-01/</link>
      <guid>https://blueberry-universe.cn/2025-01-27-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0328 奇偶链表</source>
      <description>0328 奇偶链表
你好啊，我是蓝莓，今天是每日一题的第 37 天。
题目清单：一起刷力扣
引用力扣题目：328 奇偶链表
题目描述
给定单链表的头节点 head ，将所有索引为奇数的节点和索引为偶数的节点分别组合在一起，然后返回重新排序的列表。
第一个节点的索引被认为是 奇数 ， 第二个节点的索引为 偶数 ，以此类推。
请注意，偶数组和奇数组内部的相...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 37 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/odd-even-linked-list/description/" target="_blank" rel="noopener noreferrer">328 奇偶链表</a></p>
<h2>题目描述</h2>
<p>给定单链表的头节点 <code>head</code> ，将所有索引为奇数的节点和索引为偶数的节点分别组合在一起，然后返回重新排序的列表。</p>
<p><strong>第一个</strong>节点的索引被认为是 <strong>奇数</strong> ， <strong>第二个</strong>节点的索引为 <strong>偶数</strong> ，以此类推。</p>
<p>请注意，偶数组和奇数组内部的相对顺序应该与输入时保持一致。</p>
<p>你必须在 <code>O(1)</code> 的额外空间复杂度和 <code>O(n)</code> 的时间复杂度下解决这个问题。</p>
<p><strong>示例 1:</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: head = [1,2,3,4,5]</span>
<span class="line">输出: [1,3,5,2,4]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2:</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: head = [2,1,3,5,6,4,7]</span>
<span class="line">输出: [2,3,6,7,1,5,4]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示:</strong></p>
<ul>
<li><code>n == </code> 链表中的节点数</li>
<li><code>0 &lt;= n &lt;= 104</code></li>
<li><code>-106 &lt;= Node.val &lt;= 106</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目和 <code>86 分隔链表</code> 非常相似</li>
<li>同样的，使用两个虚拟头结点来存储对应类别的节点</li>
<li>遍历原始的链表，不停的摘下一个元素然后放在对应分类的链表中</li>
<li>最后将两个链表进行合并即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* oddEvenList(ListNode* head) {</span>
<span class="line">        ListNode* oddHead = new ListNode(-1, nullptr);</span>
<span class="line">        ListNode* evenHead = new ListNode(-1, nullptr);</span>
<span class="line"></span>
<span class="line">        ListNode* oddCur = oddHead;</span>
<span class="line">        ListNode* evenCur = evenHead;</span>
<span class="line"></span>
<span class="line">        ListNode* cur = head;</span>
<span class="line">        bool isOdd = true;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line"></span>
<span class="line">            if( isOdd ) {</span>
<span class="line">                oddCur-&gt;next = cur;</span>
<span class="line">                oddCur = cur;</span>
<span class="line">            } else {</span>
<span class="line">                evenCur-&gt;next = cur;</span>
<span class="line">                evenCur = cur;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            cur-&gt;next = nullptr;</span>
<span class="line">            cur = next;</span>
<span class="line">            isOdd = !isOdd;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* res = nullptr;</span>
<span class="line"></span>
<span class="line">        if( oddHead-&gt;next != nullptr ) {</span>
<span class="line">            res = oddHead-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( res == nullptr ) {</span>
<span class="line">            res = evenHead-&gt;next;</span>
<span class="line">        } else {</span>
<span class="line">            oddCur-&gt;next = evenHead-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0231 2的幂</title>
      <link>https://blueberry-universe.cn/2025-01-27-02/</link>
      <guid>https://blueberry-universe.cn/2025-01-27-02/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0231 2的幂</source>
      <description>0231 2的幂
你好啊，我是蓝莓，今天是每日一题的第 38 天。
题目清单：一起刷力扣
引用力扣题目：231 2的幂
题目描述
给你一个整数 n，请你判断该整数是否是 2 的幂次方。如果是，返回 true ；否则，返回 false 。
如果存在一个整数 x 使得 n == 2x ，则认为 n 是 2 的幂次方。
示例 1：

示例 2：

示例 3：...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 38 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/power-of-two/description/" target="_blank" rel="noopener noreferrer">231 2的幂</a></p>
<h2>题目描述</h2>
<p>给你一个整数 <code>n</code>，请你判断该整数是否是 2 的幂次方。如果是，返回 <code>true</code> ；否则，返回 <code>false</code> 。</p>
<p>如果存在一个整数 <code>x</code> 使得 <code>n == 2x</code> ，则认为 <code>n</code> 是 2 的幂次方。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 1</span>
<span class="line">输出：true</span>
<span class="line">解释：20 = 1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 16</span>
<span class="line">输出：true</span>
<span class="line">解释：24 = 16</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 3</span>
<span class="line">输出：false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>-231 &lt;= n &lt;= 231 - 1</code></li>
</ul>
<p>**进阶：**你能够不使用循环/递归解决此问题吗？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>从整型在机器码的表示上来看，如果这个数值是 2 的整数幂的话，在数值为正的情况下低 31 个比特位只会出现一个比特位为 1 ，其余的比特位都为 0</li>
<li>2 的 0 次幂是一个特殊的情况可以单独进行判断</li>
<li>另外就是排除 n 为负数的情况</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isPowerOfTwo(int n) {</span>
<span class="line">        </span>
<span class="line">        // 排序 n 小于 0 的情况</span>
<span class="line">        if( n &lt; 0 ) {</span>
<span class="line">            return false;</span>
<span class="line">        }</span>
<span class="line">        </span>
<span class="line">        int nums = 0;</span>
<span class="line"></span>
<span class="line">        // 统计非符号位上比特位为 1 的个数</span>
<span class="line">        for( int size = 0 ; size &lt; 31 ; size++ ) {</span>
<span class="line">            if( n &gt;&gt; size &amp; 0x1 ) {</span>
<span class="line">                nums++;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( nums &gt; 1 || nums == 0 ) {</span>
<span class="line">            return false;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return true;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0445 两数相加 II</title>
      <link>https://blueberry-universe.cn/2025-01-27-03/</link>
      <guid>https://blueberry-universe.cn/2025-01-27-03/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0445 两数相加 II</source>
      <description>0445 两数相加 II
你好啊，我是蓝莓，今天是每日一题的第 39 天。
题目清单：一起刷力扣
引用力扣题目：445 两数相加 II
题目描述
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外，这两个数字都不会以零开头。
示例1：
img
...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 39 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/power-of-two/description/" target="_blank" rel="noopener noreferrer">445 两数相加 II</a></p>
<h2>题目描述</h2>
<p>给你两个 <strong>非空</strong> 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。</p>
<p>你可以假设除了数字 0 之外，这两个数字都不会以零开头。</p>
<p><strong>示例1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：l1 = [7,2,4,3], l2 = [5,6,4]</span>
<span class="line">输出：[7,8,0,7]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：l1 = [2,4,3], l2 = [5,6,4]</span>
<span class="line">输出：[8,0,7]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：l1 = [0], l2 = [0]</span>
<span class="line">输出：[0]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表的长度范围为<code> [1, 100]</code></li>
<li><code>0 &lt;= node.val &lt;= 9</code></li>
<li>输入数据保证链表代表的数字无前导 0</li>
</ul>
<p>**进阶：**如果输入链表不能翻转该如何解决？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>在做加减法的时候，肯定是要从权重最低的位开始计算</li>
<li>为了模拟这个计算过程，我们需要将链表进行翻转（虽然题目说要求不翻转，但是用栈其实都是一样的逻辑，只是没有了维护指针指向的开销而已）</li>
<li>所以在代码中实现了 <code>reverseList</code> 函数用来翻转链表，返回值为翻转后的链表头结点</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {</span>
<span class="line">        if( l1 == nullptr ) {</span>
<span class="line">            return l2;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( l2 == nullptr ) {</span>
<span class="line">            return l1;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 翻转 l1 和 l2 链表</span>
<span class="line">        ListNode* num1 = reverseList(l1);</span>
<span class="line">        ListNode* num2 = reverseList(l2);</span>
<span class="line"></span>
<span class="line">        // 创建一个虚拟头结点 dummy 用来相加结果的链表</span>
<span class="line">        ListNode* dummy = new ListNode(-1, nullptr);</span>
<span class="line">        // cur1 和 cur2 分别在 num1 和 num2 链表上滑动</span>
<span class="line">        ListNode* cur1 = num1;</span>
<span class="line">        ListNode* cur2 = num2;</span>
<span class="line"></span>
<span class="line">        // 用来表示下一轮的进位上的值</span>
<span class="line">        int carry = 0;</span>
<span class="line"></span>
<span class="line">        // carry != 0 表示 如果最后一次相加还产生了进位 还是要继续添加节点</span>
<span class="line">        while( cur1 != nullptr || cur2 != nullptr || carry != 0 ) {</span>
<span class="line">            if( cur1 != nullptr ) {</span>
<span class="line">                carry += cur1-&gt;val;</span>
<span class="line">                cur1 = cur1-&gt;next;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            if( cur2 != nullptr ) {</span>
<span class="line">                carry += cur2-&gt;val;</span>
<span class="line">                cur2 = cur2-&gt;next;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // carry % 10 为当前位置的值</span>
<span class="line">            // carry / 10 为下一位的进位值</span>
<span class="line">            ListNode* newNode = new ListNode( carry % 10, dummy-&gt;next);</span>
<span class="line">            dummy-&gt;next = newNode;</span>
<span class="line"></span>
<span class="line">            carry = carry / 10;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* res = dummy-&gt;next;</span>
<span class="line">        delete dummy;</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">    </span>
<span class="line">    // 翻转非空链表</span>
<span class="line">    ListNode* reverseList(ListNode* head) {</span>
<span class="line">        ListNode* dummy = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummy;</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        dummy-&gt;next-&gt;next = nullptr;</span>
<span class="line"></span>
<span class="line">        delete dummy;</span>
<span class="line">        return pre;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0203 移除链表元素</title>
      <link>https://blueberry-universe.cn/2025-01-28-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-28-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0203 移除链表元素</source>
      <description>0203 移除链表元素
你好啊，我是蓝莓，今天是每日一题的第 40 天。
题目清单：一起刷力扣
引用力扣题目：203 移除链表元素
题目描述
给你一个链表的头节点 head 和一个整数 val ，请你删除链表中所有满足 Node.val == val 的节点，并返回 新的头节点 。
示例 1：
img

示例 2：

示例 3：

提示：

列表中的节...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 40 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/remove-linked-list-elements/description/" target="_blank" rel="noopener noreferrer">203 移除链表元素</a></p>
<h2>题目描述</h2>
<p>给你一个链表的头节点 <code>head</code> 和一个整数 <code>val</code> ，请你删除链表中所有满足 <code>Node.val == val</code> 的节点，并返回 <strong>新的头节点</strong> 。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,6,3,4,5,6], val = 6</span>
<span class="line">输出：[1,2,3,4,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [], val = 1</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [7,7,7,7], val = 7</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>列表中的节点数目在范围 <code>[0, 104]</code> 内</li>
<li><code>1 &lt;= Node.val &lt;= 50</code></li>
<li><code>0 &lt;= val &lt;= 50</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>使用 <code>pre</code> 指向当前正在遍历的前一个节点（为了逻辑上一致，使用了虚拟头结点的技巧）</li>
<li>使用 <code>cur</code> 遍历链表，分为两种情况</li>
<li>（1）当前节点要删除，那么 <code>pre</code> 不需要移动，只需要让 <code>cur</code> 移动一下即可</li>
<li>（2）当前节点不需要删除，那么 <code>pre</code> 和 <code>cur</code> 都向前移动一次</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* removeElements(ListNode* head, int val) {</span>
<span class="line">        ListNode* dummy = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummy;</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            if( cur-&gt;val == val ) {</span>
<span class="line">                pre-&gt;next = cur-&gt;next;</span>
<span class="line">                cur = pre-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                pre = cur;</span>
<span class="line">                cur = cur-&gt;next;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return dummy-&gt;next;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0082 删除排序链表中的重复元素 II</title>
      <link>https://blueberry-universe.cn/2025-01-29-00/</link>
      <guid>https://blueberry-universe.cn/2025-01-29-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0082 删除排序链表中的重复元素 II</source>
      <description>0082 删除排序链表中的重复元素 II
你好啊，我是蓝莓，今天是每日一题的第 41 天。
题目清单：一起刷力扣
引用力扣题目：82 删除排序链表中的重复元素 II
题目描述
给定一个已排序的链表的头 head ， 删除原始链表中所有重复数字的节点，只留下不同的数字 。返回 已排序的链表 。
示例 1：
img

示例 2：
img

提示：

链表中...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 41 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/description/" target="_blank" rel="noopener noreferrer">82 删除排序链表中的重复元素 II</a></p>
<h2>题目描述</h2>
<p>给定一个已排序的链表的头 <code>head</code> ， <em>删除原始链表中所有重复数字的节点，只留下不同的数字</em> 。返回 <em>已排序的链表</em> 。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,3,4,4,5]</span>
<span class="line">输出：[1,2,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,1,1,2,3]</span>
<span class="line">输出：[2,3]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点数目在范围 <code>[0, 300]</code> 内</li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
<li>题目数据保证链表已经按升序 <strong>排列</strong></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>容易想到的是，我们可以使用两个指针 <code>pre</code> 和 <code>cur</code> ，如果我们发现两者指向的节点的值是相同的，那就说明我们发现了重复元素</li>
<li>这时候我们需要将等于我们发现的这个值的所有的节点全部删掉，方法其实很简单，我们只需要继续让 <code>cur</code> 向下继续找，找到第一个不等于当前发现的这个值的那个节点就可以了</li>
<li>随后，我们让 <code>pre</code> 的前一个节点的 <code>next</code> 指向我们发现的第一个不等于该值的节点，那么中间的链表就从逻辑上删除了</li>
<li>但是，问题来了，我们无法访问到 <code>pre</code> 的前一个节点，所以这时候可以再添加一个指针 <code>prePre</code> ，让它指向 <code>pre</code> 的前一个节点</li>
<li>最后，如果我们遍历的过程中，当前遍历到的节点是不重复的，那么就让每个指针都向后移动一次即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* deleteDuplicates(ListNode* head) {</span>
<span class="line">        // 虚拟头结点</span>
<span class="line">        ListNode* dummy = new ListNode(-1, head);</span>
<span class="line">        </span>
<span class="line">        if( head == nullptr ) {</span>
<span class="line">            return head;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* prePre = dummy;  // 指向 cur 的前一个的前一个元素</span>
<span class="line">        ListNode* pre = head;  // 指向 cur 的前一个元素</span>
<span class="line">        ListNode* cur = pre-&gt;next;  // 指向链表中的第二个节点，当前正在检查的节点</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            if( pre-&gt;val == cur-&gt;val ) {</span>
<span class="line">                // 发现重复元素</span>
<span class="line">                int val = cur-&gt;val;</span>
<span class="line">                // 将 cur 移动到当前发现的重复元素的最后一个元素的下一个节点处</span>
<span class="line">                while( cur != nullptr &amp;&amp; cur-&gt;val == val ) cur = cur-&gt;next;</span>
<span class="line"></span>
<span class="line">                // 在逻辑上截断中间这组重复的元素</span>
<span class="line">                prePre-&gt;next = cur;</span>
<span class="line">                pre = cur;</span>
<span class="line">                // cur 若为空说明已经结束；cur 不为空则继续算法</span>
<span class="line">                if( cur != nullptr ) {</span>
<span class="line">                    cur = cur-&gt;next;</span>
<span class="line">                } else {</span>
<span class="line">                    break;</span>
<span class="line">                }</span>
<span class="line">            } else {</span>
<span class="line">                // 没有发现重复的元素 正常维护指针</span>
<span class="line">                prePre = pre;</span>
<span class="line">                pre = cur;</span>
<span class="line">                cur = cur-&gt;next;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return dummy-&gt;next;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0021 合并两个有序链表</title>
      <link>https://blueberry-universe.cn/2025-01-29-01/</link>
      <guid>https://blueberry-universe.cn/2025-01-29-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0021 合并两个有序链表</source>
      <description>0021 合并两个有序链表
你好啊，我是蓝莓，今天是每日一题的第 42 天。
题目清单：一起刷力扣
引用力扣题目：21 合并两个有序链表
题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1：
img

示例 2：

示例 3：

提示：

两个链表的节点数目范围是 [0, 50]
-10...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 42 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/merge-two-sorted-lists/description/" target="_blank" rel="noopener noreferrer">21 合并两个有序链表</a></p>
<h2>题目描述</h2>
<p>将两个升序链表合并为一个新的 <strong>升序</strong> 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：l1 = [1,2,4], l2 = [1,3,4]</span>
<span class="line">输出：[1,1,2,3,4,4]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：l1 = [], l2 = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：l1 = [], l2 = [0]</span>
<span class="line">输出：[0]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>两个链表的节点数目范围是 <code>[0, 50]</code></li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
<li><code>l1</code> 和 <code>l2</code> 均按 <strong>非递减顺序</strong> 排列</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目的做法和归并排序中归并的做法很像，在归并的过程中主要分为两种情况</li>
<li>（1）两个链表都不为空，这时候选择其中值较小的节点挂在最终链表的尾部</li>
<li>（2）其中一个链表为空，另一个链表不为空，这时候就直接无脑的将不为空的那个链表的所有节点都挂在最终链表的末尾即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {</span>
<span class="line">        ListNode* cur1 = list1;</span>
<span class="line">        ListNode* cur2 = list2;</span>
<span class="line"></span>
<span class="line">        ListNode* dummy = new ListNode(-1, nullptr);</span>
<span class="line">        ListNode* cur = dummy;</span>
<span class="line"></span>
<span class="line">        while( cur1 || cur2 ) {</span>
<span class="line">            if( cur1 &amp;&amp; cur2 ) {</span>
<span class="line">                if( cur1-&gt;val &lt; cur2-&gt;val ) {</span>
<span class="line">                    cur-&gt;next = cur1;</span>
<span class="line">                    cur = cur1;</span>
<span class="line">                    cur1 = cur1-&gt;next;</span>
<span class="line">                } else {</span>
<span class="line">                    cur-&gt;next = cur2;</span>
<span class="line">                    cur = cur2;</span>
<span class="line">                    cur2 = cur2-&gt;next;</span>
<span class="line">                }</span>
<span class="line">            } else if( cur1 ) {</span>
<span class="line">                cur-&gt;next = cur1;</span>
<span class="line">                cur = cur1;</span>
<span class="line">                cur1 = cur1-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                // cur2 != nullptr</span>
<span class="line">                cur-&gt;next = cur2;</span>
<span class="line">                cur = cur2;</span>
<span class="line">                cur2 = cur2-&gt;next;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        cur-&gt;next = nullptr;</span>
<span class="line"></span>
<span class="line">        cur = dummy-&gt;next;</span>
<span class="line">        delete dummy;</span>
<span class="line"></span>
<span class="line">        return cur;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0024 两两交换链表中的节点</title>
      <link>https://blueberry-universe.cn/2025-01-29-02/</link>
      <guid>https://blueberry-universe.cn/2025-01-29-02/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0024 两两交换链表中的节点</source>
      <description>0024 两两交换链表中的节点
你好啊，我是蓝莓，今天是每日一题的第 43 天。
题目清单：一起刷力扣
引用力扣题目：24 两两交换链表中的节点
题目描述
给你一个链表，两两交换其中相邻的节点，并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题（即，只能进行节点交换）。
示例 1：
img

示例 2：

示例 3：

提示：

链表...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 43 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/swap-nodes-in-pairs/description/" target="_blank" rel="noopener noreferrer">24 两两交换链表中的节点</a></p>
<h2>题目描述</h2>
<p>给你一个链表，两两交换其中相邻的节点，并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题（即，只能进行节点交换）。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4]</span>
<span class="line">输出：[2,1,4,3]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1]</span>
<span class="line">输出：[1]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点的数目在范围 <code>[0, 100]</code> 内</li>
<li><code>0 &lt;= Node.val &lt;= 100</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>使用三个指针 <code>prePre</code> 指针即将要交换的那两个元素的前一个元素</li>
<li><code>pre</code> 指向需要交换的两个元素的第一个元素</li>
<li><code>cur</code> 指向需要交换的两个元素的第二个元素</li>
<li>接下来就按照正常逻辑完成代码就行</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* swapPairs(ListNode* head) {</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, nullptr);</span>
<span class="line"></span>
<span class="line">        if( head == nullptr || head-&gt;next == nullptr ) {</span>
<span class="line">            return head;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* prePre = dummyHead;</span>
<span class="line">        ListNode* pre = head;</span>
<span class="line">        ListNode* cur = pre-&gt;next;</span>
<span class="line"></span>
<span class="line">        while( true ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line"></span>
<span class="line">            // 交换节点</span>
<span class="line">            prePre-&gt;next = cur;</span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            pre-&gt;next = next;</span>
<span class="line"></span>
<span class="line">            // 为下一次交换做准备</span>
<span class="line">            // 看看 pre 能不能更新</span>
<span class="line">            prePre = pre;</span>
<span class="line">            if(pre-&gt;next != nullptr ) {</span>
<span class="line">                pre = pre-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                // 如果 pre 更新后为空那就不需要再继续下去了</span>
<span class="line">                break;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 看看 cur 能不能更新</span>
<span class="line">            if( pre-&gt;next != nullptr ) {</span>
<span class="line">                cur = pre-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                // 如果 cur 更新后为空 说明凑不够两个元素了</span>
<span class="line">                break;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        cur = dummyHead-&gt;next;</span>
<span class="line">        delete dummyHead;</span>
<span class="line"></span>
<span class="line">        return cur;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0025 K 个一组翻转链表</title>
      <link>https://blueberry-universe.cn/2025-02-02-00/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0025 K 个一组翻转链表</source>
      <description>0025 K 个一组翻转链表
你好啊，我是蓝莓，今天是每日一题的第 44 天。
题目清单：一起刷力扣
引用力扣题目：25 K 个一组翻转链表
题目描述
给你链表的头节点 head ，每 k 个节点一组进行翻转，请你返回修改后的链表。
k 是一个正整数，它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍，那么请将最后剩余的节点保持原有顺序。
你不...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 44 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/reverse-nodes-in-k-group/description/" target="_blank" rel="noopener noreferrer">25 K 个一组翻转链表</a></p>
<h2>题目描述</h2>
<p>给你链表的头节点 <code>head</code> ，每 <code>k</code> 个节点一组进行翻转，请你返回修改后的链表。</p>
<p><code>k</code> 是一个正整数，它的值小于或等于链表的长度。如果节点总数不是 <code>k</code> 的整数倍，那么请将最后剩余的节点保持原有顺序。</p>
<p>你不能只是单纯的改变节点内部的值，而是需要实际进行节点交换。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4,5], k = 2</span>
<span class="line">输出：[2,1,4,3,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4,5], k = 3</span>
<span class="line">输出：[3,2,1,4,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中的节点数目为 <code>n</code></li>
<li><code>1 &lt;= k &lt;= n &lt;= 5000</code></li>
<li><code>0 &lt;= Node.val &lt;= 1000</code></li>
</ul>
<p>**进阶：**你可以设计一个只用 <code>O(1)</code> 额外内存空间的算法解决此问题吗？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>同样是翻转链表，只是这次是以 k 个节点为一组进行翻转</li>
<li>在我们翻转一整个链表的时候，我们预先已经知道的信息是 <code>头结点</code>、<code>尾节点的下一个节点 nullptr</code></li>
<li>在我们知道了这两个节点后，我们就可以创建一个 <code>虚拟节点</code> 来简化代码的逻辑</li>
<li>但是每个以 k 个为一组的节点的头结点，我们是不知道的，所以我们最重要的任务其实是找到每一组的 <code>头结点</code> 和 <code>尾节点的下一个节点</code> ，那么剩下的代码逻辑就可以直接复用之前写过的逻辑了</li>
<li>关于寻找 k 个节点为一组的头节点是很简单的，第一组的头结点就是整个链表的头节点</li>
<li>我们使用 <code>cur</code> 指针，让 <code>cur</code> 向后移动 <code>k</code> 次，那么 <code>cur</code> 指向的就是第一组的 ``尾节点的下一个节点<code>，并且此时的 </code>cur` 也是第二组的头节点</li>
<li>还有重要的一点是，我们该如何检查是不是能够凑出 <code>k</code> 个节点呢？比如你看题目中的最后两个节点无法凑出 <code>3</code> 个节点为一组的情况是不需要反转的，在这里我有两个方法</li>
<li>（1）就像代码里写的那样，如果我们在向后移动 <code>k</code> 次的过程中，循环都没执行完 ，<code>cur</code>就已经指向 <code>nullptr</code> 了，这说明肯定是凑不够了，已经没法再向后移动了</li>
<li>（2）第二种情况，我们在执行循环的时候定义了一个变量 <code>i</code>，你可以把这个变量定义在循环的外部，这样，你可以在结束循环后检查一下变量 <code>i</code> 是不是刚好等于 <code>k</code> ？如果不等于的话，那说明是没有移动够 <code>k</code> 次就由于 <code>cur</code> 指向了 <code>nullptr</code> 而停了下来</li>
<li>最后我们只需要判断一下，如果凑够了 <code>k</code> 个节点就直接复用以前的反转链表的逻辑就行了</li>
<li>如果没有凑够那一定是因为 <code>cur</code> 指向了空，我们什么都不用做，整个算法也就结束了</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* reverseKGroup(ListNode* head, int k) {</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        // pre 指向需要反转的局部链表的头结点的前一个节点</span>
<span class="line">        ListNode* pre = dummyHead;</span>
<span class="line">        // 使用 cur 向后遍历 k 个节点 指向需要反转的局部链表的最后一个节点的下一个节点</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line"></span>
<span class="line">            bool ok = true;  // 在寻找过程中 如果无法凑够 k 个节点则标记为 false</span>
<span class="line">            for( int i = 0 ; i &lt; k ; i++ ) {</span>
<span class="line">                if( cur == nullptr ) {</span>
<span class="line">                    // 无法再凑够 k 个了</span>
<span class="line">                    ok = false;</span>
<span class="line">                    break;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                cur = cur-&gt;next;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 如果凑够了 k 个节点那么就翻转它</span>
<span class="line">            if(ok) {</span>
<span class="line">                // 当前的头节点便是翻转后的尾节点</span>
<span class="line">                ListNode* newEnd = pre-&gt;next;</span>
<span class="line">                // 维护指针的指向</span>
<span class="line">                pre-&gt;next = reverseList(pre-&gt;next, cur);</span>
<span class="line">                // 让尾节点指向翻转前的尾节点的下一个节点</span>
<span class="line">                newEnd-&gt;next = cur;</span>
<span class="line">                // 那么反转后的尾节点就是 cur 的前一个节点</span>
<span class="line">                pre = newEnd;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        cur = dummyHead-&gt;next;</span>
<span class="line">        delete dummyHead;</span>
<span class="line"></span>
<span class="line">        return cur;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    ListNode* reverseList(ListNode* head, ListNode* end) {</span>
<span class="line">        // head 表示需要翻转的链表头节点</span>
<span class="line">        // end 表示需要翻转的链表的尾节点的下一个节点</span>
<span class="line">        // 返回值为翻转后的链表头结点</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummyHead;</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != end ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        delete dummyHead;</span>
<span class="line">        return pre;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0147 对链表进行插入排序</title>
      <link>https://blueberry-universe.cn/2025-02-02-01/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0147 对链表进行插入排序</source>
      <description>0147 对链表进行插入排序
你好啊，我是蓝莓，今天是每日一题的第 45 天。
题目清单：一起刷力扣
引用力扣题目：147 对链表进行插入排序
题目描述
给定单个链表的头 head ，使用 插入排序 对链表进行排序，并返回 排序后链表的头 。
插入排序 算法的步骤:

插入排序是迭代的，每次只移动一个元素，直到所有元素可以形成一个有序的输出列表。
每次...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 45 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/insertion-sort-list/description/" target="_blank" rel="noopener noreferrer">147 对链表进行插入排序</a></p>
<h2>题目描述</h2>
<p>给定单个链表的头 <code>head</code> ，使用 <strong>插入排序</strong> 对链表进行排序，并返回 <em>排序后链表的头</em> 。</p>
<p><strong>插入排序</strong> 算法的步骤:</p>
<ol>
<li>插入排序是迭代的，每次只移动一个元素，直到所有元素可以形成一个有序的输出列表。</li>
<li>每次迭代中，插入排序只从输入数据中移除一个待排序的元素，找到它在序列中适当的位置，并将其插入。</li>
<li>重复直到所有输入数据插入完为止。</li>
</ol>
<p>下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时，从输入数据中删除一个元素(红色)，并就地插入已排序的列表中。</p>
<p>对链表进行插入排序。</p>
<p></p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: head = [4,2,1,3]</span>
<span class="line">输出: [1,2,3,4]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入: head = [-1,5,3,4,0]</span>
<span class="line">输出: [-1,0,3,4,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>列表中的节点数在 <code>[1, 5000]</code>范围内</li>
<li><code>-5000 &lt;= Node.val &lt;= 5000</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>在数组上使用插入排序的时候，每次插入一个数值，我们都需要把插入点和后面的数值全部向后移动一个位置，然后空出来这个插入点的位置才能让我们插入</li>
<li>所以这主要还是一个链表的基础操作，就是插入一个节点</li>
<li>在寻找插入点的时候，我们可以注意这么两个条件（按照递增排序）</li>
<li>（1）如果当前待插入节点的值大于等于当前遍历到的插入点的值，那么就继续向后遍历，否则停下来</li>
<li>（2）如果当前遍历到的这个节点已经超出了排序完成的区间范围，那么就停下来（这一点可以通过：当前的节点的是不是当前待插入节点这一条件来判断）</li>
<li>好了，明确了以上两个问题我们再来看一下如何插入一个节点</li>
<li>我们要插入的这个节点本身就是链表中的，所以我们需要先把这个节点给取下来，这个过程就已经需要我们来维护当前节点的前一个节点的 <code>next</code> 指针的指向了，所以我们需要一个 <code>pre</code> 来记录当前的节点  <code>cur</code> 的前一个节点是谁</li>
<li>那么，同时，我们还需要维护插入位置的前一个节点的指针的指向，为了减少变量的使用，我直接用一个 <code>search</code> 来代表插入位置的前一个节点了，与此同时我们通过 <code>search-&gt;next</code> 也可以访问到当前需要比较大小的那个插入点位置的节点的 <code>val</code> ；当然了，你也可以再添加一个变量，或许用着方便一些</li>
<li>最后就是维护一下 <code>cur</code> 指针指向的那个节点，如果我们需要将这个节点插入到一个为止，那么 <code>cur</code> 的 <code>next</code> 指针也需要维护一下</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* insertionSortList(ListNode* head) {</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummyHead;</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            // search 指向比较元素的前一个节点</span>
<span class="line">            ListNode* search = dummyHead;</span>
<span class="line"></span>
<span class="line">            while( cur-&gt;val &gt;= search-&gt;next-&gt;val &amp;&amp; search-&gt;next != cur ) {</span>
<span class="line">                search = search-&gt;next;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            if( search-&gt;next != cur ) {</span>
<span class="line">                // 这时候执行插入逻辑</span>
<span class="line">                ListNode* searchNext = search-&gt;next;</span>
<span class="line">                ListNode* curNext = cur-&gt;next;</span>
<span class="line">                search-&gt;next = cur;</span>
<span class="line">                cur-&gt;next = searchNext;</span>
<span class="line">                pre-&gt;next = curNext;  // pre 不需要移动</span>
<span class="line">                cur = pre-&gt;next;  // 此时应该更新 cur</span>
<span class="line">            } else {</span>
<span class="line">                // 这说明应当插入在已经排序完成的所有节点的后面</span>
<span class="line">                // 那说明 cur 当前所处位置就是正确的 直接跳过即可</span>
<span class="line">                pre = cur;</span>
<span class="line">                cur = cur-&gt;next;</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        cur = dummyHead-&gt;next;</span>
<span class="line">        delete dummyHead;</span>
<span class="line">        </span>
<span class="line">        return cur;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0148 排序链表</title>
      <link>https://blueberry-universe.cn/2025-02-02-02/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-02/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0148 排序链表</source>
      <description>0148 排序链表
你好啊，我是蓝莓，今天是每日一题的第 46 天。
题目清单：一起刷力扣
引用力扣题目：148 排序链表
题目描述
给你链表的头结点 head ，请将其按 升序 排列并返回 排序后的链表 。
示例 1：
img

示例 2：
img

示例 3：

提示：

链表中节点的数目在范围 [0, 5 * 104] 内
-105 &amp;lt;= ...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 46 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/sort-list/description/" target="_blank" rel="noopener noreferrer">148 排序链表</a></p>
<h2>题目描述</h2>
<p>给你链表的头结点 <code>head</code> ，请将其按 <strong>升序</strong> 排列并返回 <strong>排序后的链表</strong> 。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [4,2,1,3]</span>
<span class="line">输出：[1,2,3,4]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [-1,5,3,4,0]</span>
<span class="line">输出：[-1,0,3,4,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点的数目在范围 <code>[0, 5 * 104]</code> 内</li>
<li><code>-105 &lt;= Node.val &lt;= 105</code></li>
</ul>
<p>**进阶：**你可以在 <code>O(n log n)</code> 时间复杂度和常数级空间复杂度下，对链表进行排序吗？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>对于 <strong>147 对链表进行插入排序</strong> 题目，按照要求我们直接在链表上使用了插入排序</li>
<li>但是对于当前这个题目而言，插入排序的时间复杂度是 <code>O(N^2)</code> 级别的时间复杂度 不满足要求</li>
<li>相对来说，常见的排序算法，如 <code>快速排序</code>、<code>归并排序</code> 来讲，<code>归并排序</code> 是更适合在 链表上使用的</li>
<li>接下来就看一下，如何在链表作为数据结构的基础上实现归并排序</li>
<li>归并排序有两种实现方式</li>
<li>（1）自顶向下的递归方式来实现</li>
<li>（2）自底向上的方式来实现</li>
<li>在这篇文章中，我们来看看自底向上的方式怎么实现，主要有这么几方面实现的要点</li>
<li>（1）自底向上的实现过程中需要明确从每一次归并的两个子链表的长度是多大？对于每一个将要归并的链表而言，它们必须是有序的才能被正确归并，所以 <code>subSize</code> 的大小应该是从 <code>1</code> 开始，也就是第一轮归并过程中，我们把相邻的每个元素看成一个单独的链表，归并成长度为 <code>2</code> 的链表；但是 <code>subSize</code> 最大应该增长到多少就要停止了 ？可以想象一下，如果一个链表的长度为 <code>n</code> 那么我们从中间切一刀，如果 <code>subSize</code> 刚好是 <code>n/2</code> 的话，那么我们只需要再归并一次就行了，但是 <code>subSize</code> 每次都是成倍增长的，可能不会刚好增长到 <code>n/2</code>，或许上一次的 <code>subSize = 2n/5</code> 那么下一次的 <code>subSize</code> 就等于 <code>4n/5</code> ； 所以 <code>subSize</code> 如果一旦大于等于 <code>n</code> ，那么就一定已经完成归并了；记住 <code>subSize</code> 指的是归并的两个链表中的单个链表的长度，所以归并的元素最大的量是 <code>2subSize</code></li>
<li>（2）所以非常明确，应该有一层循环来处理每一轮归并过程中 <code>subSize</code> 的增长变化</li>
<li>（3）在每一轮的 <code>subSize</code> 确定后，我们如何归并？重要的是如何一步一步的找到所有成对出现的相邻的长度为 <code>subSize</code> 的链表；在这里我们使用 <code>head1</code> 来指向需要归并的第一个链表的头，使用 <code>head2</code> 来指向需要归并的第二个链表的头；使用 <code>cur</code> 来遍历整个大的链表，很容易我们可以知道 <code>head1</code> 就是 <code>cur</code> 还没有移动时所指向的节点，所以我们一开始就能确定第一组的 <code>head1</code> 是谁了。这时候我们让 <code>cur</code> 向后移动 <code>subSize</code> 个节点，我们通过 <code>cur</code> 节点的前一个节点 <code>pre</code> 可以知道 <code>head1</code> 链表的最后一个节点是谁，为了方便，我们让 <code>head1</code> 最后一个节点的 <code>next</code> 指向 <code>nullptr</code> ，而且此时 <code>cur</code> 指向的正是 <code>head2</code> 这个节点；接着我们再让 <code>cur</code> 移动 <code>subSize</code> 个节点，使用同样的方法，<code>pre</code> 指向的正是 <code>head2</code> 的最后一个节点，我们也让 <code>head2</code> 的最后一个节点指向 <code>nullptr</code> ；最后我们写一个 <code>merge</code> 函数来归并这两个链表就行了；</li>
<li>（4）在归并链表的时候，我们归并后的链表需要和 <code>head1</code> 前面的那部分衔接上，所以我们需要单独记录 <code>head1</code> 的前一个节点 <code>preHead1</code></li>
<li>（5）当我们完成一组归并后，此时的 <code>preHead1</code> 和 <code>pre</code> 都应该指向归并完成的链表的最后一个节点，因为这个节点正是下一次寻找 <code>head1</code> 的前一个节点，而且这个节点也正是 <code>cur</code> 当前所指向的节点的前一个节点；完了让链表衔接上，我们还应该让归并完成的链表的最后一个节点指向当前的 <code>cur</code> 节点（别忘了，我们之前为了 merge 过程的方便给人家改成指向 nullptr 了）；接着我们所有的变量就又回到了最初的定义</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* sortList(ListNode* head) {</span>
<span class="line">        int size = 0;</span>
<span class="line"></span>
<span class="line">        for( ListNode* cur = head ; cur != nullptr ; cur = cur-&gt;next ) {</span>
<span class="line">            size ++;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        // 当 subSize 大于 size / 2 的时候，只需要再进行最后一轮归并就结束了</span>
<span class="line">        for( int subSize = 1 ; subSize &lt; size ; subSize += subSize ) {</span>
<span class="line">            </span>
<span class="line">            ListNode* pre = dummyHead;</span>
<span class="line">            ListNode* cur = dummyHead-&gt;next;</span>
<span class="line"></span>
<span class="line">            while( cur != nullptr ) {</span>
<span class="line">                // 每完成一轮循环就要完成一组的归并</span>
<span class="line">                ListNode* preHead1 = pre;</span>
<span class="line">                ListNode* head1 = cur;</span>
<span class="line">                // 跳过前半部分</span>
<span class="line">                for( int i = 0 ; i &lt; subSize &amp;&amp; cur != nullptr ; i++ ) {</span>
<span class="line">                    pre = cur;</span>
<span class="line">                    cur = cur-&gt;next;</span>
<span class="line">                }</span>
<span class="line">                pre-&gt;next = nullptr;  // 截断 head1 链表</span>
<span class="line"></span>
<span class="line">                ListNode* head2 = cur;</span>
<span class="line">                // 跳过第二部分</span>
<span class="line">                for( int i = 0 ; i &lt; subSize &amp;&amp; cur != nullptr ; i++ ) {</span>
<span class="line">                    pre = cur;</span>
<span class="line">                    cur = cur-&gt;next;</span>
<span class="line">                }</span>
<span class="line">                pre-&gt;next = nullptr;  // 截断 head2 链表</span>
<span class="line"></span>
<span class="line">                // 合并两个链表 pre 指向合并后的链表的最后一个节点</span>
<span class="line">                pre = mergeList(preHead1, head1, head2);</span>
<span class="line">                pre-&gt;next = cur;  // 将链表链接在一起</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return dummyHead-&gt;next;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    ListNode* mergeList(ListNode* dummyHead, ListNode* head1, ListNode* head2) {</span>
<span class="line">        // 返回 合并后链表的最后一个节点</span>
<span class="line"></span>
<span class="line">        ListNode* cur = dummyHead;</span>
<span class="line"></span>
<span class="line">        ListNode* cur1 = head1;</span>
<span class="line">        ListNode* cur2 = head2;</span>
<span class="line"></span>
<span class="line">        // 一定是有一个链表被先放完的</span>
<span class="line">        while( cur1 != nullptr &amp;&amp; cur2 != nullptr ) {</span>
<span class="line">            if( cur1-&gt;val &lt; cur2-&gt;val) {</span>
<span class="line">                cur-&gt;next = cur1;</span>
<span class="line">                cur1 = cur1-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                cur-&gt;next = cur2;</span>
<span class="line">                cur2 = cur2-&gt;next;</span>
<span class="line">            }</span>
<span class="line">            cur = cur-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( cur1 != nullptr ) {</span>
<span class="line">            cur-&gt;next = cur1;</span>
<span class="line">        } else if( cur2 != nullptr ) {</span>
<span class="line">            cur-&gt;next = cur2;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        while( cur-&gt;next != nullptr ) {</span>
<span class="line">            cur = cur-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return cur;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0237 删除链表中的节点</title>
      <link>https://blueberry-universe.cn/2025-02-02-03/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-03/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0237 删除链表中的节点</source>
      <description>0237 删除链表中的节点
你好啊，我是蓝莓，今天是每日一题的第 47 天。
题目清单：一起刷力扣
引用力扣题目：237 删除链表中的节点
题目描述
有一个单链表的 head，我们想删除它其中的一个节点 node。
给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head。
链表的所有值都是 唯一的，并且保证给定的节点 node 不是链...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 47 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/delete-node-in-a-linked-list/description/" target="_blank" rel="noopener noreferrer">237 删除链表中的节点</a></p>
<h2>题目描述</h2>
<p>有一个单链表的 <code>head</code>，我们想删除它其中的一个节点 <code>node</code>。</p>
<p>给你一个需要删除的节点 <code>node</code> 。你将 <strong>无法访问</strong> 第一个节点 <code>head</code>。</p>
<p>链表的所有值都是 <strong>唯一的</strong>，并且保证给定的节点 <code>node</code> 不是链表中的最后一个节点。</p>
<p>删除给定的节点。注意，删除节点并不是指从内存中删除它。这里的意思是：</p>
<ul>
<li>给定节点的值不应该存在于链表中。</li>
<li>链表中的节点数应该减少 1。</li>
<li><code>node</code> 前面的所有值顺序相同。</li>
<li><code>node</code> 后面的所有值顺序相同。</li>
</ul>
<p><strong>自定义测试：</strong></p>
<ul>
<li>对于输入，你应该提供整个链表 <code>head</code> 和要给出的节点 <code>node</code>。<code>node</code> 不应该是链表的最后一个节点，而应该是链表中的一个实际节点。</li>
<li>我们将构建链表，并将节点传递给你的函数。</li>
<li>输出将是调用你函数后的整个链表。</li>
</ul>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [4,5,1,9], node = 5</span>
<span class="line">输出：[4,1,9]</span>
<span class="line">解释：指定链表中值为 5 的第二个节点，那么在调用了你的函数之后，该链表应变为 4 -> 1 -> 9</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [4,5,1,9], node = 1</span>
<span class="line">输出：[4,5,9]</span>
<span class="line">解释：指定链表中值为 1 的第三个节点，那么在调用了你的函数之后，该链表应变为 4 -> 5 -> 9</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点的数目范围是 <code>[2, 1000]</code></li>
<li><code>-1000 &lt;= Node.val &lt;= 1000</code></li>
<li>链表中每个节点的值都是 <strong>唯一</strong> 的</li>
<li>需要删除的节点 <code>node</code> 是 <strong>链表中的节点</strong> ，且 <strong>不是末尾节点</strong></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>题目给定一个需要删除的节点，而且这个节点一定不是链表的最后一个节点，另外我们也不知道头节点是谁</li>
<li>所以我们可以把给定节点的下一个节点的元素拷贝到当前节点，然后删除给定节点的下一个节点</li>
<li>代码非常简单</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode(int x) : val(x), next(NULL) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void deleteNode(ListNode* node) {</span>
<span class="line">        ListNode* node2 = node-&gt;next;</span>
<span class="line">        ListNode* next = node2-&gt;next;</span>
<span class="line"></span>
<span class="line">        node-&gt;val = node2-&gt;val;</span>
<span class="line">        node-&gt;next = next;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0019 删除链表的倒数第 N 个结点</title>
      <link>https://blueberry-universe.cn/2025-02-02-04/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-04/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0019 删除链表的倒数第 N 个结点</source>
      <description>0019 删除链表的倒数第 N 个结点
你好啊，我是蓝莓，今天是每日一题的第 48 天。
题目清单：一起刷力扣
引用力扣题目：19 删除链表的倒数第 N 个结点
题目描述
给你一个链表，删除链表的倒数第 n 个结点，并且返回链表的头结点。
示例 1：
img

示例 2：

示例 3：

提示：

链表中结点的数目为 sz
1 &amp;lt;= sz &amp;lt...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 48 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/" target="_blank" rel="noopener noreferrer">19 删除链表的倒数第 N 个结点</a></p>
<h2>题目描述</h2>
<p>给你一个链表，删除链表的倒数第 <code>n</code> 个结点，并且返回链表的头结点。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4,5], n = 2</span>
<span class="line">输出：[1,2,3,5]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1], n = 1</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2], n = 1</span>
<span class="line">输出：[1]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中结点的数目为 <code>sz</code></li>
<li><code>1 &lt;= sz &lt;= 30</code></li>
<li><code>0 &lt;= Node.val &lt;= 100</code></li>
<li><code>1 &lt;= n &lt;= sz</code></li>
</ul>
<p>**进阶：**你能尝试使用一趟扫描实现吗？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>最简单的思路是先遍历一遍链表看看有几个节点，然后计算出倒数第 n 个节点正着数是第几个</li>
<li>另外一种只需要遍历一遍的方法是使用两个指针，分别为 <code>slow</code> 和 <code>fast</code> ，我们让这两个指针之间空出一定的距离后再让它们两个同时向后移动，这样当 <code>fast</code> 走到底的时候，我们就可以通过 <code>slow</code> 找到倒数第 <code>n</code> 个节点是谁了</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    ListNode* removeNthFromEnd(ListNode* head, int n) {</span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line">        ListNode* slow = dummyHead;</span>
<span class="line">        ListNode* fast = head;</span>
<span class="line">        </span>
<span class="line">        // 让 fast 和 slow 之间相差 n 个节点（包括 fast 指向的节点本身）</span>
<span class="line">        for( int i = 0 ; i &lt; n ; i++ ) {</span>
<span class="line">            fast = fast-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 这时候让 slow 和 fast 同时移动</span>
<span class="line">        // 当 fast 到尾的时候 slow 刚好指向需要被删除的节点的前一个节点</span>
<span class="line">        while( fast != nullptr ) {</span>
<span class="line">            slow = slow-&gt;next;</span>
<span class="line">            fast = fast-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 在逻辑上删除节点</span>
<span class="line">        slow-&gt;next = slow-&gt;next-&gt;next;</span>
<span class="line"></span>
<span class="line">        ListNode* newHead = dummyHead-&gt;next;</span>
<span class="line">        delete dummyHead;</span>
<span class="line"></span>
<span class="line">        return newHead;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0143 重排链表</title>
      <link>https://blueberry-universe.cn/2025-02-02-05/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-05/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0143 重排链表</source>
      <description>0143 重排链表
你好啊，我是蓝莓，今天是每日一题的第 49 天。
题目清单：一起刷力扣
引用力扣题目：143 重排链表
题目描述
给定一个单链表 L 的头节点 head ，单链表 L 表示为：

请将其重新排列后变为：

不能只是单纯的改变节点内部的值，而是需要实际的进行节点交换。
示例 1：
img

示例 2：
img

提示：

链表的长度范...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 49 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/reorder-list/description/" target="_blank" rel="noopener noreferrer">143 重排链表</a></p>
<h2>题目描述</h2>
<p>给定一个单链表 <code>L</code> 的头节点 <code>head</code> ，单链表 <code>L</code> 表示为：</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">L0 → L1 → … → Ln - 1 → Ln</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>请将其重新排列后变为：</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>不能只是单纯的改变节点内部的值，而是需要实际的进行节点交换。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4]</span>
<span class="line">输出：[1,4,2,3]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,3,4,5]</span>
<span class="line">输出：[1,5,2,4,3]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表的长度范围为 <code>[1, 5 * 104]</code></li>
<li><code>1 &lt;= node.val &lt;= 1000</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>我们可以使用 <code>slow</code> 和 <code>fast</code> 指针来把原来的整个链表一分为二</li>
<li><code>slow</code> 指针每次只移动一个位置</li>
<li><code>fast</code> 指针每次移动两个位置</li>
<li>你可以自己手动模拟一下奇数个节点和偶数个节点的情况下 <code>slow</code> 指针最后移动到了哪个位置上</li>
<li>在我的代码实现中，<code>slow</code> 指针最后指向的是整个链表右侧那一半链表的头结点（而且如果是奇数的话，右侧的链表总是比左侧的链表多一个节点的）</li>
<li>好了，这样一来，我们只需要翻转右半部分的链表，然后将这两个链表按照题目要求的顺序拼接成为一个新的链表就可以了</li>
<li>最后要注意的一点是：我们要再设置一个 <code>preSlow</code> 指针用来指向左半部分链表的最后一个节点，然后将它的 <code>next</code> 指向 <code>nullptr</code></li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    void reorderList(ListNode* head) {</span>
<span class="line"></span>
<span class="line">        if(head-&gt;next == nullptr) {</span>
<span class="line">            return;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* preSlow = dummyHead;</span>
<span class="line">        ListNode* slow = head;</span>
<span class="line">        ListNode* fast = head;</span>
<span class="line"></span>
<span class="line">        while( fast != nullptr &amp;&amp; fast-&gt;next != nullptr ) {</span>
<span class="line">            preSlow = slow;</span>
<span class="line">            slow = slow-&gt;next;</span>
<span class="line">            fast = fast-&gt;next-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        preSlow-&gt;next = nullptr;</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead1 = new ListNode(-1, head);</span>
<span class="line">        ListNode* dummyHead2 = new ListNode(-1, reverseList(slow));</span>
<span class="line"></span>
<span class="line">        ListNode* cur = dummyHead;</span>
<span class="line">        ListNode* cur1 = dummyHead1-&gt;next;</span>
<span class="line">        ListNode* cur2 = dummyHead2-&gt;next;</span>
<span class="line">        </span>
<span class="line">        bool isCur1 = true;</span>
<span class="line">        while( cur1 != nullptr &amp;&amp; cur2 != nullptr ) {</span>
<span class="line">            if(isCur1) {</span>
<span class="line">                cur-&gt;next = cur1;</span>
<span class="line">                cur = cur1;</span>
<span class="line">                cur1 = cur1-&gt;next;</span>
<span class="line">            } else {</span>
<span class="line">                cur-&gt;next = cur2;</span>
<span class="line">                cur = cur2;</span>
<span class="line">                cur2 = cur2-&gt;next;</span>
<span class="line">            }</span>
<span class="line">            isCur1 = !isCur1;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 一定是左半部分的链表先被用完</span>
<span class="line">        // 我们需要把用半部分的链表的剩余部分拼接上去</span>
<span class="line">        cur-&gt;next = cur2;</span>
<span class="line"></span>
<span class="line">        delete dummyHead;</span>
<span class="line">        delete dummyHead1;</span>
<span class="line">        delete dummyHead2;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    ListNode* reverseList(ListNode* head) {</span>
<span class="line">        // head 表示需要翻转的链表头节点</span>
<span class="line">        // 返回值为翻转后的链表头结点</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummyHead;</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        dummyHead-&gt;next-&gt;next = nullptr;</span>
<span class="line"></span>
<span class="line">        delete dummyHead;</span>
<span class="line">        return pre;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0234 回文链表</title>
      <link>https://blueberry-universe.cn/2025-02-02-06/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-06/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0234 回文链表</source>
      <description>0234 回文链表
你好啊，我是蓝莓，今天是每日一题的第 50 天。
题目清单：一起刷力扣
引用力扣题目：234 回文链表
题目描述
给你一个单链表的头节点 head ，请你判断该链表是否为
回文链表
。如果是，返回 true ；否则，返回 false 。
示例 1：
img

示例 2：
img

提示：

链表中节点数目在范围[1, 105] 内
...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 50 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/palindrome-linked-list/description/" target="_blank" rel="noopener noreferrer">234 回文链表</a></p>
<h2>题目描述</h2>
<p>给你一个单链表的头节点 <code>head</code> ，请你判断该链表是否为</p>
<p>回文链表</p>
<p>。如果是，返回 <code>true</code> ；否则，返回 <code>false</code> 。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2,2,1]</span>
<span class="line">输出：true</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：head = [1,2]</span>
<span class="line">输出：false</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>链表中节点数目在范围<code>[1, 105]</code> 内</li>
<li><code>0 &lt;= Node.val &lt;= 9</code></li>
</ul>
<p>**进阶：**你能否用 <code>O(n)</code> 时间复杂度和 <code>O(1)</code> 空间复杂度解决此题？</p>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目和 <code>143 重排链表</code> 的做法非常相似，代码我都是直接复制过来的，做了一些简单的修改</li>
<li>可以参考 <code>143</code> 号题目的代码</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for singly-linked list.</span>
<span class="line"> * struct ListNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     ListNode *next;</span>
<span class="line"> *     ListNode() : val(0), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x) : val(x), next(nullptr) {}</span>
<span class="line"> *     ListNode(int x, ListNode *next) : val(x), next(next) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isPalindrome(ListNode* head) {</span>
<span class="line">        </span>
<span class="line">        // 只有一个节点的情况直接返回 true 即可</span>
<span class="line">        if( head-&gt;next == nullptr ) {</span>
<span class="line">            return true;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* preSlow = dummyHead;</span>
<span class="line">        ListNode* slow = head;</span>
<span class="line">        ListNode* fast = head;</span>
<span class="line"></span>
<span class="line">        while( fast != nullptr &amp;&amp; fast-&gt;next != nullptr ) {</span>
<span class="line">            preSlow = slow;</span>
<span class="line">            slow = slow-&gt;next;</span>
<span class="line">            fast = fast-&gt;next-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        preSlow-&gt;next = nullptr;</span>
<span class="line">        delete dummyHead;</span>
<span class="line"></span>
<span class="line">        ListNode* head1 = head;</span>
<span class="line">        ListNode* head2 = reverseList(slow);</span>
<span class="line"></span>
<span class="line">        ListNode* cur1 = head1;</span>
<span class="line">        ListNode* cur2 = head2;</span>
<span class="line"></span>
<span class="line">        while( cur1 != nullptr &amp;&amp; cur2 != nullptr ) {</span>
<span class="line">            if( cur1-&gt;val != cur2-&gt;val ) {</span>
<span class="line">                return false;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            cur1 = cur1-&gt;next;</span>
<span class="line">            cur2 = cur2-&gt;next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return true;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    ListNode* reverseList(ListNode* head) {</span>
<span class="line">        // head 表示需要翻转的链表头节点</span>
<span class="line">        // 返回值为翻转后的链表头结点</span>
<span class="line"></span>
<span class="line">        ListNode* dummyHead = new ListNode(-1, head);</span>
<span class="line"></span>
<span class="line">        ListNode* pre = dummyHead;</span>
<span class="line">        ListNode* cur = head;</span>
<span class="line"></span>
<span class="line">        while( cur != nullptr ) {</span>
<span class="line">            ListNode* next = cur-&gt;next;</span>
<span class="line">            cur-&gt;next = pre;</span>
<span class="line">            pre = cur;</span>
<span class="line">            cur = next;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        dummyHead-&gt;next-&gt;next = nullptr;</span>
<span class="line"></span>
<span class="line">        delete dummyHead;</span>
<span class="line">        return pre;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0020 有效的括号</title>
      <link>https://blueberry-universe.cn/2025-02-02-07/</link>
      <guid>https://blueberry-universe.cn/2025-02-02-07/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0020 有效的括号</source>
      <description>0020 有效的括号
你好啊，我是蓝莓，今天是每日一题的第 51 天。
题目清单：一起刷力扣
引用力扣题目：20 有效的括号
题目描述
给定一个只包括 &amp;apos;(&amp;apos;，&amp;apos;)&amp;apos;，&amp;apos;{&amp;apos;，&amp;apos;}&amp;apos;，&amp;apos;[&amp;apos;，&amp;apos;]&amp;apos; 的字符串 s ，判断字符串是否有效。
有效字符串需满足：

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 51 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/valid-parentheses/description/" target="_blank" rel="noopener noreferrer">20 有效的括号</a></p>
<h2>题目描述</h2>
<p>给定一个只包括 <code>'('</code>，<code>')'</code>，<code>'{'</code>，<code>'}'</code>，<code>'['</code>，<code>']'</code> 的字符串 <code>s</code> ，判断字符串是否有效。</p>
<p>有效字符串需满足：</p>
<ol>
<li>左括号必须用相同类型的右括号闭合。</li>
<li>左括号必须以正确的顺序闭合。</li>
<li>每个右括号都有一个对应的相同类型的左括号。</li>
</ol>
<p><strong>示例 1：</strong></p>
<p>**输入：**s = &quot;()&quot;</p>
<p>**输出：**true</p>
<p><strong>示例 2：</strong></p>
<p>**输入：**s = &quot;()[]{}&quot;</p>
<p>**输出：**true</p>
<p><strong>示例 3：</strong></p>
<p>**输入：**s = &quot;(]&quot;</p>
<p>**输出：**false</p>
<p><strong>示例 4：</strong></p>
<p>**输入：**s = &quot;([])&quot;</p>
<p>**输出：**true</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= s.length &lt;= 104</code></li>
<li><code>s</code> 仅由括号 <code>'()[]{}'</code> 组成</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个应用栈的简单题</li>
<li>（1）在遍历字符串 <code>s</code> 的过程中，如果我们遇到的是括号的左半部分，那么我们就把这个括号压入栈中</li>
<li>（2）如果在遍历的过程中，我们遇到的是括号的有半部分，那么我们就和栈顶的括号进行比对，看看是不是能够匹配成为一个完整的括号</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    bool isValid(string s) {</span>
<span class="line">        stack&lt;char&gt; record;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; s.size(); i++ ) {</span>
<span class="line">            if( s[i] == '(' || s[i] == '{' || s[i] == '[' ) {</span>
<span class="line">                record.push(s[i]);</span>
<span class="line">            } else {</span>
<span class="line">                if( record.empty() ) {</span>
<span class="line">                    return false;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                char top = record.top();</span>
<span class="line">                record.pop();</span>
<span class="line">                bool c1 = (top == '(' &amp;&amp; s[i] == ')');</span>
<span class="line">                bool c2 = (top == '{' &amp;&amp; s[i] == '}');</span>
<span class="line">                bool c3 = (top == '[' &amp;&amp; s[i] == ']');</span>
<span class="line"></span>
<span class="line">                if( c1 || c2 || c3 ) {</span>
<span class="line">                    continue;</span>
<span class="line">                } else {</span>
<span class="line">                    return false;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        if( record.size() == 0 ) {</span>
<span class="line">            return true;</span>
<span class="line">        } else {</span>
<span class="line">            return false;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0150 逆波兰表达式求值</title>
      <link>https://blueberry-universe.cn/2025-03-06-00/</link>
      <guid>https://blueberry-universe.cn/2025-03-06-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0150 逆波兰表达式求值</source>
      <description>0150 逆波兰表达式求值
你好啊，我是蓝莓，今天是每日一题的第 52 天。
题目清单：一起刷力扣
引用力扣题目：150 逆波兰表达式求值
题目描述
给你一个字符串数组 tokens ，表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意：

有效的算符为 &amp;apos;+&amp;apos;、&amp;apos;-&amp;apos;、&amp;apos;*&amp;apos; 和 &amp;apos;/&amp;apos; 。
每个操作...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 52 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/" target="_blank" rel="noopener noreferrer">150 逆波兰表达式求值</a></p>
<h2>题目描述</h2>
<p>给你一个字符串数组 <code>tokens</code> ，表示一个根据 <a href="https://baike.baidu.com/item/%E9%80%86%E6%B3%A2%E5%85%B0%E5%BC%8F/128437" target="_blank" rel="noopener noreferrer">逆波兰表示法</a> 表示的算术表达式。</p>
<p>请你计算该表达式。返回一个表示表达式值的整数。</p>
<p><strong>注意：</strong></p>
<ul>
<li>有效的算符为 <code>'+'</code>、<code>'-'</code>、<code>'*'</code> 和 <code>'/'</code> 。</li>
<li>每个操作数（运算对象）都可以是一个整数或者另一个表达式。</li>
<li>两个整数之间的除法总是 <strong>向零截断</strong> 。</li>
<li>表达式中不含除零运算。</li>
<li>输入是一个根据逆波兰表示法表示的算术表达式。</li>
<li>答案及所有中间计算结果可以用 <strong>32 位</strong> 整数表示。</li>
</ul>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：tokens = ["2","1","+","3","*"]</span>
<span class="line">输出：9</span>
<span class="line">解释：该算式转化为常见的中缀算术表达式为：((2 + 1) * 3) = 9</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：tokens = ["4","13","5","/","+"]</span>
<span class="line">输出：6</span>
<span class="line">解释：该算式转化为常见的中缀算术表达式为：(4 + (13 / 5)) = 6</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]</span>
<span class="line">输出：22</span>
<span class="line">解释：该算式转化为常见的中缀算术表达式为：</span>
<span class="line">  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5</span>
<span class="line">= ((10 * (6 / (12 * -11))) + 17) + 5</span>
<span class="line">= ((10 * (6 / -132)) + 17) + 5</span>
<span class="line">= ((10 * 0) + 17) + 5</span>
<span class="line">= (0 + 17) + 5</span>
<span class="line">= 17 + 5</span>
<span class="line">= 22</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= tokens.length &lt;= 104</code></li>
<li><code>tokens[i]</code> 是一个算符（<code>&quot;+&quot;</code>、<code>&quot;-&quot;</code>、<code>&quot;*&quot;</code> 或 <code>&quot;/&quot;</code>），或是在范围 <code>[-200, 200]</code> 内的一个整数</li>
</ul>
<p><strong>逆波兰表达式：</strong></p>
<p>逆波兰表达式是一种后缀表达式，所谓后缀就是指算符写在后面。</p>
<ul>
<li>平常使用的算式则是一种中缀表达式，如 <code>( 1 + 2 ) * ( 3 + 4 )</code> 。</li>
<li>该算式的逆波兰表达式写法为 <code>( ( 1 2 + ) ( 3 4 + ) * )</code> 。</li>
</ul>
<p>逆波兰表达式主要有以下两个优点：</p>
<ul>
<li>去掉括号后表达式无歧义，上式即便写成 <code>1 2 + 3 4 + * </code>也可以依据次序计算出正确结果。</li>
<li>适合用栈操作运算：遇到数字则入栈；遇到算符则取出栈顶两个数字进行计算，并将结果压入栈中</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个应用栈的中等题</li>
<li>对于这个题目来说，我们顺序遍历题目中所给的所有 <code>tokens</code></li>
<li>（1）如果我们发现当前正在遍历的 <code>token</code> 是一个数值的话，那么我们就把它送入栈中</li>
<li>（2）如果我们发现当前在正在遍历的 <code>token</code> 是一个运算符的话，那么我们就从栈中取出两个值按照当前的这个运算符进行运算，然后把运算后的结果放入栈中</li>
<li>有一个需要注意的地方：那就是元素的入栈顺序和出栈的顺序是相反的，对于加法和乘法这种遵守交换律的运算还好，但是对于减法和除法是不行的。我们要知道，我们从栈中取出的第一个值实际上对应于 <code>tokens</code> 数组中的后面的一个数值（这一点在代码中有体现）</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int evalRPN(vector&lt;string&gt;&amp; tokens) {</span>
<span class="line">        stack&lt;int&gt; nums;</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; tokens.size() ; i++ ) {</span>
<span class="line">            string token = tokens[i];</span>
<span class="line"></span>
<span class="line">            if( token != &quot;+&quot; &amp;&amp; token != &quot;-&quot; &amp;&amp; token != &quot;*&quot; &amp;&amp; token != &quot;/&quot; ) {</span>
<span class="line">                nums.push(stoi(token));</span>
<span class="line">            } else {</span>
<span class="line">                int num2 = nums.top();</span>
<span class="line">                nums.pop();</span>
<span class="line"></span>
<span class="line">                int num1 = nums.top();</span>
<span class="line">                nums.pop();</span>
<span class="line"></span>
<span class="line">                if( token == &quot;+&quot; ) {</span>
<span class="line">                    nums.push(num1 + num2);</span>
<span class="line">                } else if( token == &quot;-&quot; ) {</span>
<span class="line">                    nums.push(num1 - num2);</span>
<span class="line">                } else if( token == &quot;*&quot; ) {</span>
<span class="line">                    nums.push(num1 * num2);</span>
<span class="line">                } else if( token == &quot;/&quot; ) {</span>
<span class="line">                    nums.push(num1 / num2);</span>
<span class="line">                }</span>
<span class="line">            }     </span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return nums.top();</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0071 简化路径</title>
      <link>https://blueberry-universe.cn/2025-03-06-01/</link>
      <guid>https://blueberry-universe.cn/2025-03-06-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0071 简化路径</source>
      <description>0071 简化路径
你好啊，我是蓝莓，今天是每日一题的第 53 天。
题目清单：一起刷力扣
引用力扣题目：71 简化路径
题目描述
给你一个字符串 path ，表示指向某一文件或目录的 Unix 风格 绝对路径 （以 &amp;apos;/&amp;apos; 开头），请你将其转化为 更加简洁的规范路径。
在 Unix 风格的文件系统中规则如下：

一个点 &amp;apos;.&amp;apos; 表示当前目录本身。
此...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 53 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/" target="_blank" rel="noopener noreferrer">71 简化路径</a></p>
<h2>题目描述</h2>
<p>给你一个字符串 <code>path</code> ，表示指向某一文件或目录的 Unix 风格 <strong>绝对路径</strong> （以 <code>'/'</code> 开头），请你将其转化为 <strong>更加简洁的规范路径</strong>。</p>
<p>在 Unix 风格的文件系统中规则如下：</p>
<ul>
<li>一个点 <code>'.'</code> 表示当前目录本身。</li>
<li>此外，两个点 <code>'..'</code> 表示将目录切换到上一级（指向父目录）。</li>
<li>任意多个连续的斜杠（即，<code>'//'</code> 或 <code>'///'</code>）都被视为单个斜杠 <code>'/'</code>。</li>
<li>任何其他格式的点（例如，<code>'...'</code> 或 <code>'....'</code>）均被视为有效的文件/目录名称。</li>
</ul>
<p>返回的 <strong>简化路径</strong> 必须遵循下述格式：</p>
<ul>
<li>始终以斜杠 <code>'/'</code> 开头。</li>
<li>两个目录名之间必须只有一个斜杠 <code>'/'</code> 。</li>
<li>最后一个目录名（如果存在）<strong>不能</strong> 以 <code>'/'</code> 结尾。</li>
<li>此外，路径仅包含从根目录到目标文件或目录的路径上的目录（即，不含 <code>'.'</code> 或 <code>'..'</code>）。</li>
</ul>
<p>返回简化后得到的 <strong>规范路径</strong> 。</p>
<p><strong>示例 1：</strong></p>
<p>**输入：**path = &quot;/home/&quot;</p>
<p><strong>输出：</strong>&quot;/home&quot;</p>
<p><strong>解释：</strong></p>
<p>应删除尾随斜杠。</p>
<p><strong>示例 2：</strong></p>
<p>**输入：**path = &quot;/home//foo/&quot;</p>
<p><strong>输出：</strong>&quot;/home/foo&quot;</p>
<p><strong>解释：</strong></p>
<p>多个连续的斜杠被单个斜杠替换。</p>
<p><strong>示例 3：</strong></p>
<p>**输入：**path = &quot;/home/user/Documents/../Pictures&quot;</p>
<p><strong>输出：</strong>&quot;/home/user/Pictures&quot;</p>
<p><strong>解释：</strong></p>
<p>两个点 <code>&quot;..&quot;</code> 表示上一级目录（父目录）。</p>
<p><strong>示例 4：</strong></p>
<p>**输入：**path = &quot;/../&quot;</p>
<p><strong>输出：</strong>&quot;/&quot;</p>
<p><strong>解释：</strong></p>
<p>不可能从根目录上升一级目录。</p>
<p><strong>示例 5：</strong></p>
<p>**输入：**path = &quot;/.../a/../b/c/../d/./&quot;</p>
<p><strong>输出：</strong>&quot;/.../b/d&quot;</p>
<p><strong>解释：</strong></p>
<p><code>&quot;...&quot;</code> 在这个问题中是一个合法的目录名。</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= path.length &lt;= 3000</code></li>
<li><code>path</code> 由英文字母，数字，<code>'.'</code>，<code>'/'</code> 或 <code>'_'</code> 组成。</li>
<li><code>path</code> 是一个有效的 Unix 风格绝对路径。</li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个力扣的中等题</li>
<li>对于这个题目来说，我们先将 <code>path</code> 字符串按照 <code>/</code> 拆分，然后遍历拆分后的结果，对于每一个拆分后的结果判断需要做什么操作</li>
<li>（1）如果当前项是 <code>..</code> 说明我们要返回到当前所在目录的上一级目录，那其实就是把记录中的刚访问过的那个目录的名字给它删掉就好了</li>
<li>（2）如果当前的项是 <code>.</code> 说明我们要访问当前所在的目录，这说明我们什么都不用做，静静的待在当前所在的目录就可以了，直接跳过就 ok</li>
<li>（3）如果当前访问到的是以上两种情况以外的项，那么说明我们应该访问当前的这个项，所以这时候我们应该在结果中添加这一项</li>
<li>还有更多的细节都在代码中啦！</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    string simplifyPath(string path) {</span>
<span class="line">        // 先讲 path 按照 '/' 字符进行拆分</span>
<span class="line">        vector&lt;string&gt; names = split(path, '/');</span>
<span class="line">        // result 保留最后的路径中所包含的项</span>
<span class="line">        vector&lt;string&gt; result;</span>
<span class="line"></span>
<span class="line">        for( string name : names ) {</span>
<span class="line">            if( name == &quot;..&quot; ) {</span>
<span class="line">                // 如果是 .. 说明我们应该跳转到当前访问的目录的上一级目录</span>
<span class="line">                // 所以直接将当前访问的目录给 pop 出去就可以了</span>
<span class="line">                // 注意检查是不是当前目录就是根目录了</span>
<span class="line">                // 如果当前目录就是根目录，说明 result 里面没有元素</span>
<span class="line">                if( result.size() &gt;= 1 ) {</span>
<span class="line">                    result.pop_back();</span>
<span class="line">                }</span>
<span class="line">            } else if( name == &quot;.&quot; ){</span>
<span class="line">                // 如果是访问当前目录，那就直接跳过好啦</span>
<span class="line">                continue;</span>
<span class="line">            } else {</span>
<span class="line">                // 将要访问的新的目录名纳入结果中</span>
<span class="line">                result.push_back(name);</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 使用 res 来拼接最终简化后的字符串</span>
<span class="line">        string res = &quot;&quot;;</span>
<span class="line">        for( string name : result ) {</span>
<span class="line">            res += &quot;/&quot; + name;</span>
<span class="line">        }</span>
<span class="line">        </span>
<span class="line">        // 很有可能简化后的字符串就是根目录</span>
<span class="line">        // 所以我们应该看看 res 是不是为空</span>
<span class="line">        //  如果为空的话，我们直接返回根目录就可以了</span>
<span class="line">        if( res == &quot;&quot; ) {</span>
<span class="line">            return &quot;/&quot;;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 不为空则返回 res</span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    vector&lt;string&gt; split(const string&amp; str, char delimiter) {</span>
<span class="line">        // 按照 delimiter 字符将 str 字符串拆拆分为多个子串</span>
<span class="line">        // 若拆分出来的某个子串为空串的话 ==&gt; 直接丢弃</span>
<span class="line">        vector&lt;string&gt; slices;</span>
<span class="line">        int start = 0;</span>
<span class="line"></span>
<span class="line">        while( start &lt; str.size() ) {</span>
<span class="line">            // start 是上一次的拆分点的下一个字符</span>
<span class="line">            // 寻找到拆分点 end</span>
<span class="line">            int end = str.find(delimiter, start);</span>
<span class="line">            if( end == -1 ) break;</span>
<span class="line">            // 取 str[start, end) 这个区间内的元素</span>
<span class="line">            string slice = str.substr(start, end-start);</span>
<span class="line">            start = end + 1; // 让 start 移动到这一次的拆分点的下一个字符</span>
<span class="line">            // 丢弃空串</span>
<span class="line">            if( slice.empty() ) continue;</span>
<span class="line">            // 保留非空串</span>
<span class="line">            slices.push_back(slice);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 很有可能最后一个子串没有被装进结果中 ==&gt; 做一次特殊的检查</span>
<span class="line">        if( start &lt; str.size() &amp;&amp; !str.substr(start, str.size()-start).empty() ) {</span>
<span class="line">            slices.push_back(str.substr(start, str.size()-start));</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return slices;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0102 二叉树的层序遍历</title>
      <link>https://blueberry-universe.cn/2025-03-07-00/</link>
      <guid>https://blueberry-universe.cn/2025-03-07-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0102 二叉树的层序遍历</source>
      <description>0102 二叉树的层序遍历
你好啊，我是蓝莓，今天是每日一题的第 54 天。
题目清单：一起刷力扣
引用力扣题目：102 二叉树的层序遍历
题目描述
给你二叉树的根节点 root ，返回其节点值的 层序遍历 。 （即逐层地，从左到右访问所有节点）。
示例 1：
img

示例 2：

示例 3：

提示：

树中节点数目在范围 [0, 2000] 内
...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 54 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/binary-tree-level-order-traversal/description/" target="_blank" rel="noopener noreferrer">102 二叉树的层序遍历</a></p>
<h2>题目描述</h2>
<p>给你二叉树的根节点 <code>root</code> ，返回其节点值的 <strong>层序遍历</strong> 。 （即逐层地，从左到右访问所有节点）。</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = [3,9,20,null,null,15,7]</span>
<span class="line">输出：[[3],[9,20],[15,7]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = [1]</span>
<span class="line">输出：[[1]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>树中节点数目在范围 <code>[0, 2000]</code> 内</li>
<li><code>-1000 &lt;= Node.val &lt;= 1000</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个力扣的中等题</li>
<li>这是数据结构中的广度优先基础方法</li>
<li>只是在我们进行广度优先搜索的过程中要想个办法明确当前遍历的是哪一层，因为我们的节点一旦放入队列中后，我们就不知道这个节点是不是不属于我们正在遍历的那一层了</li>
<li>但是，你可以明确的知道，二叉树的最上层只有一个根节点，在你遍历这一层的时候，你通过判断它这个节点的左子树和右子树是否为空的情况时，也就知道了下一层有多少个节点了，其实当你遍历完当前这一层的时候，队列中装进去的刚好就是下一层的所有节点</li>
<li>好啦，那么具体的逻辑看代码就懂啦</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for a binary tree node.</span>
<span class="line"> * struct TreeNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     TreeNode *left;</span>
<span class="line"> *     TreeNode *right;</span>
<span class="line"> *     TreeNode() : val(0), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;int&gt;&gt; levelOrder(TreeNode* root) {</span>
<span class="line">        // q 队列用于辅助广度优先搜索</span>
<span class="line">        queue&lt;TreeNode*&gt; q;</span>
<span class="line">        // res 里面的每一个 vector&lt;int&gt; 用来存储一层的元素</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line"></span>
<span class="line">        // 如果这是一个空二叉树 直接返回空的 res 即可</span>
<span class="line">        if( root == nullptr ) {</span>
<span class="line">            return res;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        // 为把第一层的元素装进去做准备</span>
<span class="line">        res.push_back(vector&lt;int&gt;());</span>
<span class="line"></span>
<span class="line">        int level = 0;  // 当前正在遍历的层（自顶向下从 0 开始）</span>
<span class="line">        int nodeNums = 1;  // 当前层的节点数量</span>
<span class="line">        q.push(root);  // 将 root 节点放入队列中</span>
<span class="line"></span>
<span class="line">        while(!q.empty()) {</span>
<span class="line">            TreeNode* node = q.front();</span>
<span class="line">            q.pop();</span>
<span class="line"></span>
<span class="line">            // 若左子树不为空则将左子树的根节点放入队列中</span>
<span class="line">            if( node-&gt;left != nullptr ) {</span>
<span class="line">                q.push(node-&gt;left);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 若右子树不为空则将右子树的根节点放入队列中</span>
<span class="line">            if( node-&gt;right != nullptr ) {</span>
<span class="line">                q.push(node-&gt;right);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            // 将当前遍历的节点的值放入 level 层的 vector&lt;int&gt; 中</span>
<span class="line">            res[level].push_back(node-&gt;val);</span>
<span class="line">            nodeNums--;  // 将当前层的节点计数减少 1</span>
<span class="line">            </span>
<span class="line">            // 如果当前层已经遍历完了 并且 队列中还有元素</span>
<span class="line">            // 那么维护这些变量</span>
<span class="line">            if( nodeNums &lt;= 0 &amp;&amp; !q.empty() ) {</span>
<span class="line">                level++;  // 移动到下一层</span>
<span class="line">                res.push_back(vector&lt;int&gt;());  // 初始化下一层的 vector&lt;int&gt;</span>
<span class="line">                nodeNums = q.size();  // 当前队列中存储的元素便是下一层的所有节点</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0107 二叉树的层序遍历 II</title>
      <link>https://blueberry-universe.cn/2025-05-22-00/</link>
      <guid>https://blueberry-universe.cn/2025-05-22-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0107 二叉树的层序遍历 II</source>
      <description>0107 二叉树的层序遍历 II
你好啊，我是蓝莓，今天是每日一题的第 55 天。
题目清单：一起刷力扣
引用力扣题目：107 二叉树的层序遍历 II
题目描述
给你二叉树的根节点 root ，返回其节点值 自底向上的层序遍历 。 （即按从叶子节点所在层到根节点所在的层，逐层从左向右遍历）
示例 1：
img

示例 2：

示例 3：

提示：

树...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 55 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/" target="_blank" rel="noopener noreferrer">107 二叉树的层序遍历 II</a></p>
<h2>题目描述</h2>
<p>给你二叉树的根节点 <code>root</code> ，返回其节点值 <strong>自底向上的层序遍历</strong> 。 （即按从叶子节点所在层到根节点所在的层，逐层从左向右遍历）</p>
<p><strong>示例 1：</strong></p>
<p></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = [3,9,20,null,null,15,7]</span>
<span class="line">输出：[[15,7],[9,20],[3]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = [1]</span>
<span class="line">输出：[[1]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>树中节点数目在范围 <code>[0, 2000]</code> 内</li>
<li><code>-1000 &lt;= Node.val &lt;= 1000</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个力扣的中等题</li>
<li>这是数据结构中的二叉树广度优先基础方法</li>
<li>这个题目和 102 号题目是非常相似的</li>
<li>在 102 号题目，我们已经知道如何把每二叉树每一层的值给遍历出来了</li>
<li>在当前这个题目中，它要求我们按照正常的广度优先遍历的相反的顺序将每一层的节点的值输出</li>
<li>那么，我们只需要按照 102 号题目的方法遍历，然后将代码中 res 数组颠倒一下顺序即可</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for a binary tree node.</span>
<span class="line"> * struct TreeNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     TreeNode *left;</span>
<span class="line"> *     TreeNode *right;</span>
<span class="line"> *     TreeNode() : val(0), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;int&gt;&gt; levelOrderBottom(TreeNode* root) {</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line">        queue&lt;TreeNode*&gt; q;</span>
<span class="line"></span>
<span class="line">        if( root == nullptr ) {</span>
<span class="line">            return res;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int level = 0;</span>
<span class="line">        q.push(root);</span>
<span class="line"></span>
<span class="line">        while( !q.empty() ) {</span>
<span class="line">            int size = q.size();</span>
<span class="line">            res.push_back(vector&lt;int&gt;());</span>
<span class="line">            </span>
<span class="line">            for( int i = 0 ; i &lt; size ; i++ ) {</span>
<span class="line">                TreeNode* front = q.front();</span>
<span class="line">                q.pop();</span>
<span class="line">                </span>
<span class="line">                if( front-&gt;left ) {</span>
<span class="line">                    q.push(front-&gt;left);</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( front-&gt;right ) {</span>
<span class="line">                    q.push(front-&gt;right);</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                res[level].push_back(front-&gt;val);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            ++level;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int half = level / 2;</span>
<span class="line">        for( int i = 0 ; i &lt; half ; i++ ) {</span>
<span class="line">            swap(res[i], res[level-i-1]);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0103 二叉树的锯齿形层序遍历</title>
      <link>https://blueberry-universe.cn/2025-05-22-01/</link>
      <guid>https://blueberry-universe.cn/2025-05-22-01/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0103 二叉树的锯齿形层序遍历</source>
      <description>0103 二叉树的锯齿形层序遍历
你好啊，我是蓝莓，今天是每日一题的第 56 天。
题目清单：一起刷力扣
引用力扣题目：103 二叉树的锯齿形层序遍历
题目描述
给你二叉树的根节点 root ，返回其节点值的 锯齿形层序遍历 。（即先从左往右，再从右往左进行下一层遍历，以此类推，层与层之间交替进行）。
示例 1：
img

示例 2：

示例 3：

...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 56 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/description/" target="_blank" rel="noopener noreferrer">103 二叉树的锯齿形层序遍历</a></p>
<h2>题目描述</h2>
<p>给你二叉树的根节点 <code>root</code> ，返回其节点值的 <strong>锯齿形层序遍历</strong> 。（即先从左往右，再从右往左进行下一层遍历，以此类推，层与层之间交替进行）。</p>
<p><strong>示例 1：</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2021/02/19/tree1.jpg" alt="img"></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = [3,9,20,null,null,15,7]</span>
<span class="line">输出：[[3],[20,9],[15,7]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = [1]</span>
<span class="line">输出：[[1]]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 3：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：root = []</span>
<span class="line">输出：[]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li>树中节点数目在范围 <code>[0, 2000]</code> 内</li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目和 102 以及 107 题目依然是相似的</li>
<li>当前题目的代码，直接沿用了 107 号题目的代码，仅仅在代码最后的交换顺序的部分做出了简单的修改</li>
<li>我们依然是先按照正常的广度优先遍历的方式遍历二叉树</li>
<li>遍历完成后，我们去改变 <code>res</code> 数组中某些层的顺序，从而满足题目的要求</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for a binary tree node.</span>
<span class="line"> * struct TreeNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     TreeNode *left;</span>
<span class="line"> *     TreeNode *right;</span>
<span class="line"> *     TreeNode() : val(0), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;vector&lt;int&gt;&gt; zigzagLevelOrder(TreeNode* root) {</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line">        queue&lt;TreeNode*&gt; q;</span>
<span class="line"></span>
<span class="line">        if( root == nullptr ) {</span>
<span class="line">            return res;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int level = 0;</span>
<span class="line">        q.push(root);</span>
<span class="line"></span>
<span class="line">        while( !q.empty() ) {</span>
<span class="line">            int size = q.size();</span>
<span class="line">            res.push_back(vector&lt;int&gt;());</span>
<span class="line">            </span>
<span class="line">            for( int i = 0 ; i &lt; size ; i++ ) {</span>
<span class="line">                TreeNode* front = q.front();</span>
<span class="line">                q.pop();</span>
<span class="line">                </span>
<span class="line">                if( front-&gt;left ) {</span>
<span class="line">                    q.push(front-&gt;left);</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( front-&gt;right ) {</span>
<span class="line">                    q.push(front-&gt;right);</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                res[level].push_back(front-&gt;val);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            ++level;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 1 ; i &lt; level ; i+=2 ) {</span>
<span class="line">            int sz = res[i].size();</span>
<span class="line">            int half = sz / 2;</span>
<span class="line">            for( int j = 0 ; j &lt; half ; j++ ) {</span>
<span class="line">                swap(res[i][j], res[i][sz-j-1]);</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return res;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
      <enclosure url="https://assets.leetcode.com/uploads/2021/02/19/tree1.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>0199 二叉树的右视图</title>
      <link>https://blueberry-universe.cn/2025-05-22-02/</link>
      <guid>https://blueberry-universe.cn/2025-05-22-02/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0199 二叉树的右视图</source>
      <description>0199 二叉树的右视图
你好啊，我是蓝莓，今天是每日一题的第 57 天。
题目清单：一起刷力扣
引用力扣题目：199 二叉树的右视图
题目描述
给定一个二叉树的 根节点 root，想象自己站在它的右侧，按照从顶部到底部的顺序，返回从右侧所能看到的节点值。
示例 1：
**输入：**root = [1,2,3,null,5,null,4]
输出：[1,...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 57 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/binary-tree-right-side-view/description/" target="_blank" rel="noopener noreferrer">199 二叉树的右视图</a></p>
<h2>题目描述</h2>
<p>给定一个二叉树的 <strong>根节点</strong> <code>root</code>，想象自己站在它的右侧，按照从顶部到底部的顺序，返回从右侧所能看到的节点值。</p>
<p><strong>示例 1：</strong></p>
<p>**输入：**root = [1,2,3,null,5,null,4]</p>
<p><strong>输出：</strong>[1,3,4]</p>
<p><strong>解释：</strong></p>
<p></p>
<p><strong>示例 2：</strong></p>
<p>**输入：**root = [1,2,3,4,null,null,null,5]</p>
<p><strong>输出：</strong>[1,3,4,5]</p>
<p><strong>解释：</strong></p>
<p></p>
<p><strong>示例 3：</strong></p>
<p>**输入：**root = [1,null,3]</p>
<p><strong>输出：</strong>[1,3]</p>
<p><strong>示例 4：</strong></p>
<p>**输入：**root = []</p>
<p><strong>输出：</strong>[]</p>
<p><strong>提示:</strong></p>
<ul>
<li>二叉树的节点个数的范围是 <code>[0,100]</code></li>
<li><code>-100 &lt;= Node.val &lt;= 100</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这个题目和 107 题目依然是相似的</li>
<li>当前题目的代码，直接沿用了 107 号题目的代码</li>
<li>我们依然是先按照正常的广度优先遍历的方式遍历二叉树</li>
<li>遍历完成后，我们去改变 <code>res</code> 数组中某些层的顺序，从而满足题目的要求</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/**</span>
<span class="line"> * Definition for a binary tree node.</span>
<span class="line"> * struct TreeNode {</span>
<span class="line"> *     int val;</span>
<span class="line"> *     TreeNode *left;</span>
<span class="line"> *     TreeNode *right;</span>
<span class="line"> *     TreeNode() : val(0), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}</span>
<span class="line"> *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}</span>
<span class="line"> * };</span>
<span class="line"> */</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    vector&lt;int&gt; rightSideView(TreeNode* root) {</span>
<span class="line">        vector&lt;vector&lt;int&gt;&gt; res;</span>
<span class="line">        vector&lt;int&gt; view;</span>
<span class="line">        queue&lt;TreeNode*&gt; q;</span>
<span class="line"></span>
<span class="line">        if( root == nullptr ) {</span>
<span class="line">            return view;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        int level = 0;</span>
<span class="line">        q.push(root);</span>
<span class="line"></span>
<span class="line">        while( !q.empty() ) {</span>
<span class="line">            int size = q.size();</span>
<span class="line">            res.push_back(vector&lt;int&gt;());</span>
<span class="line">            </span>
<span class="line">            for( int i = 0 ; i &lt; size ; i++ ) {</span>
<span class="line">                TreeNode* front = q.front();</span>
<span class="line">                q.pop();</span>
<span class="line">                </span>
<span class="line">                if( front-&gt;left ) {</span>
<span class="line">                    q.push(front-&gt;left);</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( front-&gt;right ) {</span>
<span class="line">                    q.push(front-&gt;right);</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                res[level].push_back(front-&gt;val);</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            ++level;</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        for( int i = 0 ; i &lt; res.size() ; i++ ) {</span>
<span class="line">            view.push_back(res[i][res[i].size()-1]);</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return view;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>0279 完全平方数</title>
      <link>https://blueberry-universe.cn/2025-05-27-00/</link>
      <guid>https://blueberry-universe.cn/2025-05-27-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">0279 完全平方数</source>
      <description>0279 完全平方数
你好啊，我是蓝莓，今天是每日一题的第 58 天。
题目清单：一起刷力扣
引用力扣题目：279 完全平方数
题目描述
给你一个整数 n ，返回 和为 n 的完全平方数的最少数量 。
完全平方数 是一个整数，其值等于另一个整数的平方；换句话说，其值等于一个整数自乘的积。例如，1、4、9 和 16 都是完全平方数，而 3 和 11 不是...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓，今天是每日一题的第 58 天。</p>
<p><strong>题目清单</strong>：<a href="https://blueberry-universe.cn/lc/index.html" target="_blank" rel="noopener noreferrer">一起刷力扣</a></p>
<p><strong>引用力扣题目</strong>：<a href="https://leetcode.cn/problems/perfect-squares/description/" target="_blank" rel="noopener noreferrer">279 完全平方数</a></p>
<h2>题目描述</h2>
<p>给你一个整数 <code>n</code> ，返回 <em>和为 <code>n</code> 的完全平方数的最少数量</em> 。</p>
<p><strong>完全平方数</strong> 是一个整数，其值等于另一个整数的平方；换句话说，其值等于一个整数自乘的积。例如，<code>1</code>、<code>4</code>、<code>9</code> 和 <code>16</code> 都是完全平方数，而 <code>3</code> 和 <code>11</code> 不是。</p>
<p><strong>示例 1：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 12</span>
<span class="line">输出：3 </span>
<span class="line">解释：12 = 4 + 4 + 4</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>示例 2：</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">输入：n = 13</span>
<span class="line">输出：2</span>
<span class="line">解释：13 = 4 + 9</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= n &lt;= 104</code></li>
</ul>
<h2>实现</h2>
<p><strong>思路</strong></p>
<ul>
<li>这是一个中等难度的题目</li>
<li>解决这个问题可以采用 图的 广度优先搜索的方法</li>
<li>图的顶点 是当前剩余还需要拼凑的数值</li>
<li>图的边     是完全平方数的平方</li>
<li>经过一条边，就相当于让顶点的值减去了一个完全平方数的平方从而来到了一个新的顶点</li>
<li>因此，广度优先搜索的层数的深度，就是我们要求的值</li>
</ul>
<p><strong>C++ 代码实现</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">/ 图的广度优先搜索</span>
<span class="line">// 看遍历到第几层的时候能够遍历到节点 0</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int numSquares(int n) {</span>
<span class="line">        // v, step</span>
<span class="line">        queue&lt;pair&lt;int, int&gt;&gt; q;</span>
<span class="line">        vector&lt;bool&gt; visted(n+1, false);</span>
<span class="line">        q.push( make_pair(n, 0) );</span>
<span class="line"></span>
<span class="line">        while( !q.empty() ) {</span>
<span class="line">            pair&lt;int, int&gt; v = q.front();</span>
<span class="line">            q.pop();</span>
<span class="line"></span>
<span class="line">            int num = v.first;</span>
<span class="line">            int step = v.second;</span>
<span class="line"></span>
<span class="line">            if( num == 0 ) {</span>
<span class="line">                return step;</span>
<span class="line">            }</span>
<span class="line"></span>
<span class="line">            for( int i = 1 ; num - i*i &gt;= 0 ; i++ ) {</span>
<span class="line">                int next = num - i*i;</span>
<span class="line">                if( visted[next] == false) {</span>
<span class="line">                    q.push( make_pair(next, step+1) );</span>
<span class="line">                    visted[next] = true;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return -1;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>C++ 代码实现优化</strong></p>
<div class="language-c++ line-numbers-mode" data-highlighter="prismjs" data-ext="c++"><pre><code class="language-c++"><span class="line">// 优化：提前算法的结束步骤</span>
<span class="line">class Solution {</span>
<span class="line">public:</span>
<span class="line">    int numSquares(int n) {</span>
<span class="line">        // v, step</span>
<span class="line">        queue&lt;pair&lt;int, int&gt;&gt; q;</span>
<span class="line">        vector&lt;bool&gt; visted(n+1, false);</span>
<span class="line">        q.push( make_pair(n, 0) );</span>
<span class="line"></span>
<span class="line">        while( !q.empty() ) {</span>
<span class="line">            pair&lt;int, int&gt; v = q.front();</span>
<span class="line">            q.pop();</span>
<span class="line"></span>
<span class="line">            int num = v.first;</span>
<span class="line">            int step = v.second;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line">            for( int i = 1 ; ; i++ ) {</span>
<span class="line">                int next = num - i*i;</span>
<span class="line">                if( next &lt; 0 ) {</span>
<span class="line">                    break;</span>
<span class="line">                }</span>
<span class="line"></span>
<span class="line">                if( visted[next] == false) {</span>
<span class="line">                    </span>
<span class="line">                    // 提前返回的步骤</span>
<span class="line">                    if( next == 0 ) {</span>
<span class="line">                        return step+1;</span>
<span class="line">                    }</span>
<span class="line"></span>
<span class="line">                    q.push( make_pair(next, step+1) );</span>
<span class="line">                    visted[next] = true;</span>
<span class="line">                }</span>
<span class="line">            }</span>
<span class="line">        }</span>
<span class="line"></span>
<span class="line">        return -1;</span>
<span class="line">    }</span>
<span class="line">};</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title></title>
      <link>https://blueberry-universe.cn/2023-09-27-00/</link>
      <guid>https://blueberry-universe.cn/2023-09-27-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml"></source>
      <description>硬核：计算机是如何跑起来的
哈喽，在今天这篇文章中，我们一起来看看当计算机通电之后是怎么开始运行代码的？
从我们第一次开始学习写代码，大多数人应该都是学习的C语言吧，我们就直接在操作系统的基础上开始编译并且运行的，那么操作系统本身也是一个程序，操作系统这段代码是怎么开始运行的呢？
本文是基于 x86 架构的 cpu ，在实验中使用的宿主机操作系统是 U...</description>
      <content:encoded><![CDATA[<h2>硬核：计算机是如何跑起来的</h2>
<p>哈喽，在今天这篇文章中，我们一起来看看当计算机通电之后是怎么开始运行代码的？</p>
<p>从我们第一次开始学习写代码，大多数人应该都是学习的C语言吧，我们就直接在操作系统的基础上开始编译并且运行的，那么操作系统本身也是一个程序，操作系统这段代码是怎么开始运行的呢？</p>
<p>本文是基于 x86 架构的 cpu ，在实验中使用的宿主机操作系统是 Ubuntu，让我们体验一下掌控 CPU 执行大权的感觉</p>
<h2>1 谋权篡位第一程</h2>
<p>大家应该都听说过 BIOS 这个东西吧，它的全名叫做 Base Input Output System 也就是基本输入输出系统。BIOS 也是一段程序，只不过它是在硬件出厂的时候就已经被写死在存储器中了，CPU 会自动地去执行 BIOS 这段代码，也就是说这都是被事先设计好的，一开始就是会自动的去干这件事儿，这是被写死在硬件层面的。</p>
<p>当然，我们的计算机能做的事情很多，仅仅能执行 BIOS 这段代码肯定是不够的，为了能够让我们接任 CPU 的大权，BIOS 这段代码会先对计算机做一些检查，最终 BIOS 会自动地去加载磁盘上的第 1 个扇区的 512B 的内容到内存的 0x7c00 地址处，紧接着加载完成后，CPU 的 IP 寄存器就是指向 <code>0x7c00</code> 地址处开始执行被加载到内存中的那 512B 的代码啦。</p>
<p>另外 BIOS 还提供了一些功能，比如我们可以通过 BIOS 所提供的功能从硬盘的某个扇区开始读取数据，还可以向屏幕上输出一些最简单的字符。</p>
<p><strong>划重点</strong></p>
<p>总之，你现在知道啦，我们最早能够接任 CPU 大权的代码就必须要写在磁盘的第 1 个扇区那 512B 的地方。</p>
<p>你会不会有疑问？我们的操作系统可不止 512B，虽然说我们的操作系统不止 512B，但是我们可以在这 512B 内再写一个加载程序，然后让这个程序去加载一个更大的程序。</p>
<p>这里所说的加载，其实就是把磁盘上的数据复制到内存上的某个位置而已，因为CPU只能直接读取内存中的数据。</p>
<p><strong>操作系统的加载</strong></p>
<p>实际上操作系统的加载分为了三个步骤</p>
<ol>
<li>BIOS 把MBR加载到 0x7c00 处的位置</li>
<li>MBR 将操作系统加载器加载到内存的某个位置</li>
<li>操作系统的加载器再去加载操作系统的代码到内存</li>
</ol>
<p>在这篇文章中，我们只关心磁盘的第一个扇区，我们会在磁盘的第一个扇区写入一些代码，然后使用 BIOS 的功能在屏幕上输出一些字符，这样就可以代表我们的这个代码顺利被夹在而且被 CPU 执行啦。</p>
<h2>2 搭建实验环境</h2>
<ol>
<li>安装汇编编译器</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> nasm</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ol start="2">
<li>安装 qemu 模拟器</li>
</ol>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> qemu-system-x86</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ol start="3">
<li>制作一个磁盘镜像</li>
</ol>
<p>这样我们就拥有了一个磁盘镜像，我么使用 disk.img 作为 qemu 虚拟机的硬盘</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">dd if=/dev/zero of=disk.img bs=512 count=20480</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2>3 让我们运行一下</h2>
<p>我们先来写一个汇编文件就叫 mbr.S</p>
<p>首先来看这段汇编代码的 <code>vstart=0x7c00</code> 的作用，当我们使用这个伪指令的时候，我们就是告诉汇编语言的编译器说，这段代码我以后肯定是要从内存地址的 <code>0x7c00</code> 处开始放的，所以在你编译这段代码的时候，有关内存的寻址操作也要按照 <code>0x7c00</code> 这个位置作为其实地址来编译代码。</p>
<p>在代码中你还会看到 <code>0xb800</code> 这样一个地址，因为 <code>0xb800</code>是被写入到段寄存器中的，所以真实的内存起始地址应该是 <code>0xb8000</code>。可以先不管这个内容，因为这个就涉及到了上古时代的 8086 CPU 的寻址方式了。</p>
<p>如果我们想要在屏幕上显示一些内容的话，我们只需要将数据写入从这个地址开始的内存单元即可。</p>
<p>从 <code>0xb8000</code> 开始每两个字节作为一组，其中低地址的那个字节用来存储写入的字符的值，其中高地址的那个字节用来存储这个字符显示时候的背景色这类东西。</p>
<p>比如说: <code>mov byte [gs:0x00],'h'</code> 和 <code>mov byte [gs:0x01],0xA4</code> 这两条指令，其中第一条指令就是在 <code>0xb8000</code>地址处写入了字符 <code>h</code> 的 <code>ASCII</code>值，在高地址的那个字节 <code>0xb8001</code> 地址处写入了字符 <code>h</code> 对应的颜色以及底色，其中高字节中的低4位控制底色，高4位控制字符的颜色，你可以动手修改它的值自己尝试一下。</p>
<p>在这段汇编代码的最后你还看到了 <code>   times 510-($-$$) db 0</code>和 <code>db 0x55,0xaa</code> 这两条指令，这两条指令达到的效果就是在第一个扇区的最后两个字节的位置写入了 <code>0x55</code> 和 <code>0xaa</code> 这两个内容。因为第一个扇区的内容被自动加载到 <code>0x7c00</code>处还有一个要求，那就是这个扇区的最后两个位置要填入 <code>0x55</code> 和 <code>0xaa</code> ，只有这样，这个扇区的数据才会被 BIOS 加载。这都是约定好的，不必在意，没有什么特殊的原因。</p>
<p><strong>编译汇编代码</strong></p>
<div class="language-assembly line-numbers-mode" data-highlighter="prismjs" data-ext="assembly"><pre><code class="language-assembly"><span class="line">SECTION MBR vstart=0x7c00         </span>
<span class="line">   mov ax,cs      </span>
<span class="line">   mov ds,ax</span>
<span class="line">   mov es,ax</span>
<span class="line">   mov ss,ax</span>
<span class="line">   mov fs,ax</span>
<span class="line">   mov sp,0x7c00</span>
<span class="line">   mov ax,0xb800</span>
<span class="line">   mov gs,ax     </span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x00],'h'</span>
<span class="line">   mov byte [gs:0x01],0xA4</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x02],'e'</span>
<span class="line">   mov byte [gs:0x03],0xA5</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x04],'l'</span>
<span class="line">   mov byte [gs:0x05],0xB6	  </span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x06],'l'</span>
<span class="line">   mov byte [gs:0x07],0xC7</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x08],'o'</span>
<span class="line">   mov byte [gs:0x09],0xD8</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x0A],' '</span>
<span class="line">   mov byte [gs:0x0B],0xE9</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x0C],'w'</span>
<span class="line">   mov byte [gs:0x0D],0xFA</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x0E],'o'</span>
<span class="line">   mov byte [gs:0x0F],0xA4</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x10],'r'</span>
<span class="line">   mov byte [gs:0x11],0xAC</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x12],'l'</span>
<span class="line">   mov byte [gs:0x13],0xAD</span>
<span class="line"></span>
<span class="line">   mov byte [gs:0x14],'d'</span>
<span class="line">   mov byte [gs:0x15],0xAE</span>
<span class="line"></span>
<span class="line">   jmp $</span>
<span class="line"></span>
<span class="line">   times 510-($-$$) db 0</span>
<span class="line">   db 0x55,0xaa</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>好啦，接着我把 mbr.S 放在文件中进行编译，其中我们使用命令 <code>nasm -f bin -o mbr.bin mbr.S</code></p>
<ol>
<li>参数 -f 就是 format ，就是说我们编译出来的代码需要是 二进制格式的</li>
<li>参数 -o 就是 output，用来表示输出文件的文件名</li>
</ol>
<p></p>
<p><strong>做个磁盘镜像</strong></p>
<p>那么我就在当前目录下制作一个磁盘镜像好啦</p>
<p>使用命令 <code>dd if=/dev/zero of=disk.img bs=512 count=20480</code></p>
<p></p>
<p>当我们做好磁盘镜像后，我们需要把我们编译生成的二进制代码原封不动的拷贝到磁盘镜像 disk.img 的第 1 个扇区</p>
<p>我们可以通过命令 <code>dd if=mbr.bin of=./disk.img conv=notrunc</code>来把 mbr.bin 中的数据拷贝到 disk.img 中</p>
<ol>
<li>参数 if 是 input file 就是输入文件</li>
<li>参数 of 是 output file 就是输出文件</li>
<li>conv = notrunc 代表的意思是，当拷贝 mbr.bin 的数据覆盖进 disk.img 的时候，不要清空覆盖不到的那些位置上的 disk.img 的数据，比如 mbr.bin 只有 512B，那么就原有的 disk.img 中的第 2 个扇区和后边的那些扇区的数据都不会受到影响。</li>
</ol>
<p></p>
<p><strong>奔跑吧！</strong></p>
<p>最后，我们就让 qemu 工作起来，<code>hello world</code> 仪式感来咯！</p>
<p>使用命令 <code>qemu-system-i386 -m 128M -drive file=disk.img,index=0,media=disk,format=raw</code></p>
<p>在这些参数中，我们使用 file 用来指定虚拟机启动时所使用的磁盘镜像，因为我执行这条命令的时候 <code>disk.img</code> 就在当前目录下，所以我直接这样写就可以啦。</p>
<p></p>
<p>当我们的 qemu 虚拟机跑起来之后，就有了下图的效果</p>
<p></p>
<p>哈哈哈，我第一次跑到这里的时候还是很兴奋的，这可是我们在计算机上能够接手的第一个程序嗷！</p>
<p>你会发现屏幕上还有一些其他的字，那是因为我们并没有清空屏幕上的内容，当我们在 <code>0xb8000</code> 处开始写入数据的时候，原来这个地方的数据就被我们覆盖啦，所以就变成了图中的这个样子。</p>


]]></content:encoded>
    </item>
    <item>
      <title></title>
      <link>https://blueberry-universe.cn/2024-05-08-00/</link>
      <guid>https://blueberry-universe.cn/2024-05-08-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml"></source>
      <description>编译 Linux 内核 &amp;amp;&amp;amp; 添加系统调用
在这篇文章中做一个小实验，先对 Linux 内核的源码做一些小改动，我们就只是在其中添加一个系统调用就好了，然后我们对内核进行编译并使用它
目标：

添加系统调用
编译 &amp;amp;&amp;amp; 安装
测试我们的系统调用

1 添加系统调用
实验环境
我这次是直接在安装了 Ubuntu 系统的虚拟...</description>
      <content:encoded><![CDATA[<h2>编译 Linux 内核 &amp;&amp; 添加系统调用</h2>
<p>在这篇文章中做一个小实验，先对 Linux 内核的源码做一些小改动，我们就只是在其中添加一个系统调用就好了，然后我们对内核进行编译并使用它</p>
<p><strong>目标：</strong></p>
<ol>
<li>添加系统调用</li>
<li>编译 &amp;&amp; 安装</li>
<li>测试我们的系统调用</li>
</ol>
<h2>1 添加系统调用</h2>
<p><strong>实验环境</strong></p>
<p>我这次是直接在安装了 Ubuntu 系统的虚拟机中进行实验的，当前系统的内核版本是 <code>ubuntu 6.8.0</code></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/expr/linux-6.8.9$ <span class="token function">uname</span> <span class="token parameter variable">-a</span></span>
<span class="line">Linux ubuntu <span class="token number">6.8</span>.0-31-generic <span class="token comment">#31-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 20 00:40:06 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>下载源码</strong></p>
<p>我们得先下载一个 Linux 的内核源码</p>
<p>传送门：https://kernel.org/</p>
<p>我们直接来到这里进行下载就可以了，你可以下载一个你感兴趣的版本，而我就直接下载 <code>6.8.9</code> 这个版本了</p>
<p></p>
<p>为了简单，我就不对下载后的内核源码进行正确性的验证了，通常来说是没有问题的，在文章的最后我给出了我参考的资料，这些资料里面会有更详细的内容</p>
<p>好啦，我已经把源码下载到了这个路径</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/expr$ <span class="token builtin class-name">pwd</span></span>
<span class="line">/home/blueberry/expr</span>
<span class="line">blueberry@ubuntu:~/expr$ <span class="token function">ls</span></span>
<span class="line">linux-6.8.9.tar.xz</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>解压</strong></p>
<p>对源码文件进行解压，解压后 <code>linux-6.8.9</code> 就是我们要的源码啦</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:~/expr$ tar -xf linux-6.8.9.tar.xz </span>
<span class="line">blueberry@ubuntu:~/expr$ ls</span>
<span class="line">linux-6.8.9  linux-6.8.9.tar.xz</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>修改源码</strong></p>
<p>你只需要按照我接下来的操作进行就可以了，先不用特别在意为什么要这么做</p>
<p><code>1. 修改 syscall_64.tbl</code></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/arch/x86/entry/syscalls$ <span class="token builtin class-name">pwd</span></span>
<span class="line">/home/blueberry/expr/linux-6.8.9/arch/x86/entry/syscalls</span>
<span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/arch/x86/entry/syscalls$ <span class="token function">ls</span> <span class="token parameter variable">-ltr</span></span>
<span class="line">total <span class="token number">40</span></span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">15278</span> May  <span class="token number">2</span> <span class="token number">14</span>:35 syscall_64.tbl</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">18346</span> May  <span class="token number">2</span> <span class="token number">14</span>:35 syscall_32.tbl</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry  <span class="token number">2527</span> May  <span class="token number">2</span> <span class="token number">14</span>:35 Makefile</span>
<span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/arch/x86/entry/syscalls$ <span class="token function">vim</span> syscall_64.tbl</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>来到这个文件的 346 行，在这里添加一行；这里的 335 是系统调用号，你可以根据你下载的内核版本，自己选择一个合适的系统调用号填上去就可以了，只要不和别的重复即可</p>
<div class="language-txt line-numbers-mode" data-highlighter="prismjs" data-ext="txt"><pre><code class="language-txt"><span class="line"> 335     64      helloworld           sys_helloworld</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p><code>2. 修改 syscalls.h</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/include/linux$ pwd</span>
<span class="line">/home/blueberry/expr/linux-6.8.9/include/linux</span>
<span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/include/linux$ vim syscalls.h</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>我们在 933 行添加一行如下的代码：</p>
<div class="language-c line-numbers-mode" data-highlighter="prismjs" data-ext="c"><pre><code class="language-c"><span class="line">asmlinkage <span class="token keyword">long</span> <span class="token function">sys_helloworld</span><span class="token punctuation">(</span><span class="token keyword">char</span> <span class="token operator">*</span> words<span class="token punctuation">,</span> <span class="token keyword">int</span> count<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p><code>3. 修改 sys.c</code></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/kernel$ <span class="token builtin class-name">pwd</span></span>
<span class="line">/home/blueberry/expr/linux-6.8.9/kernel</span>
<span class="line">blueberry@ubuntu:~/expr/linux-6.8.9/kernel$ <span class="token function">vim</span> sys.c</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>我们直接来到这个文件的末尾，添加如下代码：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">asmlinkage int sys_helloworld<span class="token punctuation">(</span>char * words, int count<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        int ret<span class="token punctuation">;</span></span>
<span class="line">        char buffer<span class="token punctuation">[</span><span class="token number">512</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">        if<span class="token punctuation">(</span>count <span class="token operator">>=</span> <span class="token number">512</span><span class="token punctuation">)</span><span class="token punctuation">{</span></span>
<span class="line">                <span class="token builtin class-name">return</span> -1<span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">        copy_from_user<span class="token punctuation">(</span>buffer, words, count<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        ret <span class="token operator">=</span> printk<span class="token punctuation">(</span><span class="token string">"User Mode says %s to the Kernel Mode!"</span>, buffer<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token builtin class-name">return</span> ret<span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">SYSCALL_DEFINE2<span class="token punctuation">(</span>helloworld, char *, words, int, count<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token builtin class-name">return</span> sys_helloworld<span class="token punctuation">(</span>words, count<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<h2>2 编译 &amp;&amp; 安装</h2>
<p>接下来我们就来编译内核并将它进行安装</p>
<p><strong>安装所必要的工具</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/expr/linux-6.8.9$ <span class="token function">sudo</span> <span class="token function">apt</span> <span class="token function">install</span> <span class="token function">bc</span> binutils bison dwarves flex gcc <span class="token function">git</span> gnupg2 <span class="token function">gzip</span> libelf-dev libncurses5-dev libssl-dev <span class="token function">make</span> openssl pahole perl-base <span class="token function">rsync</span> <span class="token function">tar</span> xz-utils</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>生成配置文件 .config</strong></p>
<p>Linux 内核的编译是受到这么一个文件进行控制的，比如哪些模块要被编译，哪些干脆不要了，这些内容都是在这样一个配置文件中的</p>
<p>既然我们编译好的内核最终是要安装到虚拟机这台机器本身的，那么最好的方式当然是参考虚拟机本身的内核所使用的配置文件啦，在我的机器上，这个默认的配置文件在这个位置：</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:/boot$ pwd</span>
<span class="line">/boot</span>
<span class="line">blueberry@ubuntu:/boot$ ls -ltr</span>
<span class="line">total 89272</span>
<span class="line">-rw</span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>裸机程序也能调试？</title>
      <link>https://blueberry-universe.cn/2024-11-13-00/</link>
      <guid>https://blueberry-universe.cn/2024-11-13-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">裸机程序也能调试？</source>
      <description>裸机程序也能调试？
你好啊，我是蓝莓 ；
如果你想自己动手写一个简单的操作系统内核，一定需要去调试这个程序，毕竟可能出现很多的 bug，可是这种不依赖于具体的操作系统的代码，我们该怎么去调试呢？
好在，我们已经有了 QEMU 虚拟机和 GDB 这样的调试工具，能够帮助我们来调试它。那么在这篇文章就使用一个非常简单的例子，来演示一下，如何调试一个裸机上运...</description>
      <content:encoded><![CDATA[
<p>你好啊，我是蓝莓 ；</p>
<p>如果你想自己动手写一个简单的操作系统内核，一定需要去调试这个程序，毕竟可能出现很多的 bug，可是这种不依赖于具体的操作系统的代码，我们该怎么去调试呢？</p>
<p>好在，我们已经有了 QEMU 虚拟机和 GDB 这样的调试工具，能够帮助我们来调试它。那么在这篇文章就使用一个非常简单的例子，来演示一下，如何调试一个裸机上运行的代码。</p>
<h2>1、写一段代码</h2>
<p>在我的这篇文章中介绍了什么是 MBR 并且介绍了，我们该如何在 QEMU 中启动一个不依赖于具体操作系统的代码。在阅读本文之前可以先去读这篇文章。</p>
<p>传送门：<a href="https://mp.weixin.qq.com/s/R__LXz7OjXrhKn9lu_TsJA" target="_blank" rel="noopener noreferrer">硬核：计算机是如何跑起来的，MBR谋权篡位</a></p>
<p>在 MBR 的那篇文章中我们使用的汇编语言格式是 intel 风格的。但是在本篇文章中，我们要使用 GCC 来对我们的文件进行编译，所以只好采用 AT&amp;T 风格的汇编了。</p>
<p>所以，我们就有了下面的这段汇编代码，你直接复制就好啦；</p>
<div class="language-asm line-numbers-mode" data-highlighter="prismjs" data-ext="asm"><pre><code class="language-asm"><span class="line">.section .text</span>
<span class="line">.global _start</span>
<span class="line">.code16                # 使用 16 位代码模式</span>
<span class="line"></span>
<span class="line">_start:</span>
<span class="line">    jmp main           # 跳转到主程序</span>
<span class="line"></span>
<span class="line"># 使用 0x7C00 作为程序加载基地址</span>
<span class="line">main:</span>
<span class="line">    movw %cs, %ax      </span>
<span class="line">    movw %ax, %ds</span>
<span class="line">    movw %ax, %es</span>
<span class="line">    movw %ax, %ss</span>
<span class="line">    movw %ax, %fs</span>
<span class="line">    movw $0x7c00, %sp</span>
<span class="line">    movw $0xb800, %ax</span>
<span class="line">    movw %ax, %gs     </span>
<span class="line"></span>
<span class="line">    movb $'h', %gs:(0x00)</span>
<span class="line">    movb $0xA4, %gs:(0x01)</span>
<span class="line"></span>
<span class="line">    movb $'e', %gs:(0x02)</span>
<span class="line">    movb $0xA5, %gs:(0x03)</span>
<span class="line"></span>
<span class="line">    movb $'l', %gs:(0x04)</span>
<span class="line">    movb $0xB6, %gs:(0x05)</span>
<span class="line"></span>
<span class="line">    movb $'l', %gs:(0x06)</span>
<span class="line">    movb $0xC7, %gs:(0x07)</span>
<span class="line"></span>
<span class="line">    movb $'o', %gs:(0x08)</span>
<span class="line">    movb $0xD8, %gs:(0x09)</span>
<span class="line"></span>
<span class="line">    movb $' ', %gs:(0x0A)</span>
<span class="line">    movb $0xE9, %gs:(0x0B)</span>
<span class="line"></span>
<span class="line">    movb $'w', %gs:(0x0C)</span>
<span class="line">    movb $0xFA, %gs:(0x0D)</span>
<span class="line"></span>
<span class="line">    movb $'o', %gs:(0x0E)</span>
<span class="line">    movb $0xA4, %gs:(0x0F)</span>
<span class="line"></span>
<span class="line">    movb $'r', %gs:(0x10)</span>
<span class="line">    movb $0xAC, %gs:(0x11)</span>
<span class="line"></span>
<span class="line">    movb $'l', %gs:(0x12)</span>
<span class="line">    movb $0xAD, %gs:(0x13)</span>
<span class="line"></span>
<span class="line">    movb $'d', %gs:(0x14)</span>
<span class="line">    movb $0xAE, %gs:(0x15)</span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"># 填充到 510 字节</span>
<span class="line">.space 510 - (.-_start)</span>
<span class="line"></span>
<span class="line"># MBR 标识符 0xAA55</span>
<span class="line">.word 0xAA55</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这段代码的作用其实就是在屏幕上输出 <code>hello world</code>；而且，这还是彩色的呢！哈哈哈</p>
<p></p>
<h2>2、编译 &amp;&amp; 链接 &amp;&amp; 写入二进制程序</h2>
<p>我们已经准备好了代码，那么就让我们编译一下叭</p>
<p><strong>创建虚拟磁盘</strong></p>
<p>可以看到，这样，我们的目录中就有了我们写好的代码 <code>mbr.S</code> 以及使用 <code>dd</code> 命令创建好的一个给 <code>QEMU</code> 使用的虚拟磁盘啦。</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  mbr <span class="token function">dd</span> <span class="token assign-left variable">if</span><span class="token operator">=</span>/dev/zero <span class="token assign-left variable">of</span><span class="token operator">=</span>disk.img <span class="token assign-left variable">bs</span><span class="token operator">=</span><span class="token number">512</span> <span class="token assign-left variable">count</span><span class="token operator">=</span><span class="token number">20480</span></span>
<span class="line"><span class="token number">20480</span>+0 records <span class="token keyword">in</span></span>
<span class="line"><span class="token number">20480</span>+0 records out</span>
<span class="line"><span class="token number">10485760</span> bytes <span class="token punctuation">(</span><span class="token number">10</span> MB, <span class="token number">10</span> MiB<span class="token punctuation">)</span> copied, <span class="token number">0.0675632</span> s, <span class="token number">155</span> MB/s</span>
<span class="line">➜  mbr <span class="token function">ls</span> <span class="token parameter variable">-ltr</span></span>
<span class="line">total <span class="token number">10244</span></span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry     <span class="token number">1029</span> Nov <span class="token number">13</span> <span class="token number">20</span>:01 mbr.S</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">10485760</span> Nov <span class="token number">13</span> <span class="token number">20</span>:06 disk.img</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>生成二进制代码</strong></p>
<p>在这里经过编译和链接后生成的 <code>mbr.bin</code> 就是一个二进制代码，这里面放的就是 CPU 可以直接拿来执行的指令，不包含任何没有用的信息。</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">➜  mbr gcc -m32 -ffreestanding -c mbr.S -o mbr.o </span>
<span class="line">➜  mbr  ld -m elf_i386 -Ttext 0x7c00 --oformat binary mbr.o -o mbr.bin</span>
<span class="line">➜  mbr ls -ltr</span>
<span class="line">total 10252</span>
<span class="line">-rw-rw-r-- 1 blueberry blueberry     1029 Nov 13 20:01 mbr.S</span>
<span class="line">-rw-rw-r-- 1 blueberry blueberry 10485760 Nov 13 20:06 disk.img</span>
<span class="line">-rw-rw-r-- 1 blueberry blueberry     1000 Nov 13 20:12 mbr.o</span>
<span class="line">-rwxrwxr-x 1 blueberry blueberry      512 Nov 13 20:13 mbr.bin</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>我们把 <code>mbr.bin</code> 这个二进制代码直接写入到 <code>disk.img</code> 的第一个扇区上；这样，当 QEMU 启动的时候，BIOS 就会自动把这部分代码加载到内存的 <code>0x7c00</code> 处运行啦。</p>
<p><strong>写入二进制程序</strong></p>
<p>直接使用 <code>dd</code> 命令写入就好啦，现在 mbr.bin 就被我们写入到了 disk.img 中</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  mbr <span class="token function">dd</span> <span class="token assign-left variable">if</span><span class="token operator">=</span>mbr.bin <span class="token assign-left variable">of</span><span class="token operator">=</span>disk.img <span class="token assign-left variable">bs</span><span class="token operator">=</span><span class="token number">512</span> <span class="token assign-left variable">count</span><span class="token operator">=</span><span class="token number">1</span></span>
<span class="line"><span class="token number">1</span>+0 records <span class="token keyword">in</span></span>
<span class="line"><span class="token number">1</span>+0 records out</span>
<span class="line"><span class="token number">512</span> bytes copied, <span class="token number">0.000340003</span> s, <span class="token number">1.5</span> MB/s</span>
<span class="line">➜  mbr <span class="token function">ls</span> <span class="token parameter variable">-ltr</span></span>
<span class="line">total <span class="token number">16</span></span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">1029</span> Nov <span class="token number">13</span> <span class="token number">20</span>:01 mbr.S</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">1000</span> Nov <span class="token number">13</span> <span class="token number">20</span>:12 mbr.o</span>
<span class="line">-rwxrwxr-x <span class="token number">1</span> blueberry blueberry  <span class="token number">512</span> Nov <span class="token number">13</span> <span class="token number">20</span>:13 mbr.bin</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry  <span class="token number">512</span> Nov <span class="token number">13</span> <span class="token number">20</span>:16 disk.img</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>编译生成带有符号的 ELF 文件</strong></p>
<p>在我们调试的过程中，我们希望能看到机器上正在执行的指令和我们编写的汇编源码之间的映射关系，每当机器代码之后之后能够对应到相应的汇编代码的某一行上。<code>ELF</code> 文件就是做这件事情用的，比如我们在 <code>mbr.S</code> 中有一个符号是 <code>main</code> 那么在 <code>ELF</code> 文件中就可以记录上 <code>main</code> 和具体的地址是一个怎样的映射关系，它又对应到了 <code>mbr.S</code> 这个文件中的第几行代码。所有的这些内容都可以记录在 <code>ELF</code> 文件中。</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  mbr gcc <span class="token parameter variable">-m32</span> <span class="token parameter variable">-nostdlib</span> <span class="token parameter variable">-g</span> -fdebug-prefix-map<span class="token operator">=</span><span class="token environment constant">$PWD</span><span class="token operator">=</span>. <span class="token parameter variable">-c</span> <span class="token parameter variable">-o</span> mbr.o mbr.S</span>
<span class="line">➜  mbr ld <span class="token parameter variable">-m</span> elf_i386 <span class="token parameter variable">-Ttext</span> 0x7c00 <span class="token parameter variable">-o</span> mbr.elf mbr.o</span>
<span class="line">➜  mbr <span class="token function">ls</span> <span class="token parameter variable">-ltr</span></span>
<span class="line">total <span class="token number">24</span></span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">1029</span> Nov <span class="token number">13</span> <span class="token number">20</span>:01 mbr.S</span>
<span class="line">-rwxrwxr-x <span class="token number">1</span> blueberry blueberry  <span class="token number">512</span> Nov <span class="token number">13</span> <span class="token number">20</span>:13 mbr.bin</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry  <span class="token number">512</span> Nov <span class="token number">13</span> <span class="token number">20</span>:16 disk.img</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">1748</span> Nov <span class="token number">13</span> <span class="token number">20</span>:21 mbr.o</span>
<span class="line">-rwxrwxr-x <span class="token number">1</span> blueberry blueberry <span class="token number">4520</span> Nov <span class="token number">13</span> <span class="token number">20</span>:21 mbr.elf</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol>
<li>-g : 这个参数就是在告诉 gcc 要把我们提及到的那些符号信息记录下来</li>
<li>-fdebug-prefix-map=$PWD=. : 用来告诉 gcc 我们的源码文件 <code>mbr.S</code> 是在 <code>ELF</code> 文件的同一个目录中的</li>
<li>-Ttext 0x7c00 : 因为我们的代码是要加载到 0x7c00 处运行的，所以我们需要告诉链接器，我们的代码未来要在哪儿执行</li>
</ol>
<p>最后我们就有了 <code>mbr.elf</code> 这个中间人了。</p>
<h2>3、调试裸机程序</h2>
<p><strong>启动 QEMU</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">qemu-system-i386 -m 128M -drive file=disk.img,index=0,media=disk,format=raw -s -S</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><ol>
<li>
<p>-s：这是 -gdb tcp::1234 的简写，表示 QEMU 会在 TCP 端口 1234 上启动一个 GDB 服务器。这样就可以使用 GDB（或其他兼容的调试器）远程连接到这个端口，进行调试。</p>
</li>
<li>
<p>-S：启动虚拟机时会暂停 CPU，这样虚拟机不会立即运行。这个选项适用于调试时的初始化。使用这个选项后，虚拟机会在启动后暂停，直到使用调试器发送“继续”命令时才会运行。</p>
</li>
</ol>
<p>如果你是使用终端连接的 Linux 系统，因此不能够显示 <code>QEMU</code> 创建的图形界面的话可以使用如下命令启动，这样就可以使用没有界面的形式启动了</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">qemu-system-i386 -m 128M -drive file=disk.img,index=0,media=disk,format=raw -s -S -nographic</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>好啦，我们先打开一个终端启动 <code>QEMU</code> 之后，我们再打开另外一个终端使用 <code>GDB</code> 连接 <code>QEMU</code> 进行远程调试。</p>
<p><strong>gdb 调试</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  mbr <span class="token function">ls</span> <span class="token parameter variable">-ltr</span></span>
<span class="line">total <span class="token number">24</span></span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">1029</span> Nov <span class="token number">13</span> <span class="token number">20</span>:01 mbr.S</span>
<span class="line">-rwxrwxr-x <span class="token number">1</span> blueberry blueberry  <span class="token number">512</span> Nov <span class="token number">13</span> <span class="token number">20</span>:13 mbr.bin</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry  <span class="token number">512</span> Nov <span class="token number">13</span> <span class="token number">20</span>:16 disk.img</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry <span class="token number">1748</span> Nov <span class="token number">13</span> <span class="token number">20</span>:21 mbr.o</span>
<span class="line">-rwxrwxr-x <span class="token number">1</span> blueberry blueberry <span class="token number">4520</span> Nov <span class="token number">13</span> <span class="token number">20</span>:21 mbr.elf</span>
<span class="line">➜  mbr gdb mbr.elf</span>
<span class="line">GNU gdb <span class="token punctuation">(</span>Ubuntu <span class="token number">9.2</span>-0ubuntu1~20.04.2<span class="token punctuation">)</span> <span class="token number">9.2</span></span>
<span class="line"><span class="token punctuation">..</span>. 此处省略一大堆输出信息 <span class="token punctuation">..</span>.</span>
<span class="line">Reading symbols from mbr.elf<span class="token punctuation">..</span>.</span>
<span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> target remote :1234</span>
<span class="line">Remote debugging using :1234</span>
<span class="line">0x0000fff0 <span class="token keyword">in</span> ?? <span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> <span class="token builtin class-name">break</span> _start</span>
<span class="line">Breakpoint <span class="token number">1</span> at 0x7c00: <span class="token function">file</span> mbr.S, line <span class="token number">6</span>.</span>
<span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> <span class="token builtin class-name">break</span> main</span>
<span class="line">Breakpoint <span class="token number">2</span> at 0x7c02: <span class="token function">file</span> mbr.S, line <span class="token number">10</span>.</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol>
<li>首先输入 <code>gdb mbr.elf</code> 进入到 <code>gdb</code> 的调试界面中</li>
<li><code>target remote :1234</code> : 进入到 gdb 的调试界面后输入这个命令，用来告诉 <code>gdb</code> 我们要连接哪个 <code>QEMU</code> 进行调试，那当然就是启动在 <code>localhost:1234</code> 这个位置上的 <code>QEMU</code> 进行调试啦</li>
<li><code>break _start</code> : 在 <code>mbr.S</code> 的源码文件中 <code>_start</code> 这个位置上打一个断点，当然啦，你也可以直接指定某一条指令所处的内存地址进行打断点的。看到没有！你会发现它告诉你 <code>_start</code> 这个符号是在 <code>mbr.S</code> 的第 6 行。<code>Breakpoint 1 at 0x7c00: file mbr.S, line 6.</code></li>
<li><code>break main</code> : 这个和 3 是同理的</li>
</ol>
<p><strong>让程序跑起来</strong></p>
<p>这时候我们在 <code>gdb</code> 调试界面输入 <code>c</code> 就可以让它运行到第一个断点处停下来啦。这时候，你还可以输入  <code>list</code> 命令，你就看到了对应的汇编源码啦。</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> c</span>
<span class="line">Continuing.</span>
<span class="line"></span>
<span class="line">Breakpoint <span class="token number">1</span>, _start <span class="token punctuation">(</span><span class="token punctuation">)</span> at mbr.S:6</span>
<span class="line"><span class="token number">6</span>	    jmp main           <span class="token comment"># 跳转到主程序</span></span>
<span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> list</span>
<span class="line"><span class="token number">1</span>	.section .text</span>
<span class="line"><span class="token number">2</span>	.global _start</span>
<span class="line"><span class="token number">3</span>	.code16                <span class="token comment"># 使用 16 位代码模式</span></span>
<span class="line"><span class="token number">4</span>	</span>
<span class="line"><span class="token number">5</span>	_start:</span>
<span class="line"><span class="token number">6</span>	    jmp main           <span class="token comment"># 跳转到主程序</span></span>
<span class="line"><span class="token number">7</span>	</span>
<span class="line"><span class="token number">8</span>	<span class="token comment"># 使用 0x7C00 作为程序加载基地址</span></span>
<span class="line"><span class="token number">9</span>	main:</span>
<span class="line"><span class="token number">10</span>	    movw %cs, %ax      </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>再跑一下子</strong></p>
<p>这次我们可以运行到 <code>main</code> 这个位置啦，或许你会好奇 <code>main</code> 难道不是位于 <code>mbr.S</code> 的第 9 行吗？另外，<code>_start</code> 是位于 <code>mbr.S</code> 的第 5 行，可是为什么显示的是第 6 行呢。</p>
<p><code>Breakpoint 1, _start () at mbr.S:6</code></p>
<p><code>Breakpoint 2, main () at mbr.S:10</code></p>
<p>这可能是因为 <code>main</code> 和 <code>_start</code> 只是一个符号，并不是真实要执行的指令，其实 <code>main</code> 和它下边的第一条指令 <code>movw %cs, %ax </code> 对应的是同一个地址，<code>main</code>符号本身就只是 <code>movw %cs, %ax </code> 指令所处的地址的一个别名而已。</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> c</span>
<span class="line">Continuing.</span>
<span class="line"></span>
<span class="line">Breakpoint <span class="token number">2</span>, main <span class="token punctuation">(</span><span class="token punctuation">)</span> at mbr.S:10</span>
<span class="line"><span class="token number">10</span>	    movw %cs, %ax      </span>
<span class="line"><span class="token punctuation">(</span>gdb<span class="token punctuation">)</span> list</span>
<span class="line"><span class="token number">5</span>	_start:</span>
<span class="line"><span class="token number">6</span>	    jmp main           <span class="token comment"># 跳转到主程序</span></span>
<span class="line"><span class="token number">7</span>	</span>
<span class="line"><span class="token number">8</span>	<span class="token comment"># 使用 0x7C00 作为程序加载基地址</span></span>
<span class="line"><span class="token number">9</span>	main:</span>
<span class="line"><span class="token number">10</span>	    movw %cs, %ax      </span>
<span class="line"><span class="token number">11</span>	    movw %ax, %ds</span>
<span class="line"><span class="token number">12</span>	    movw %ax, %es</span>
<span class="line"><span class="token number">13</span>	    movw %ax, %ss</span>
<span class="line"><span class="token number">14</span>	    movw %ax, %fs</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>好啦！太棒了！恭喜你完成了，你可以尝试着在每一次输出字符的位置都打上一个断点，然后看着字符一个一个的输出出来试试呢，完成这个测试，一定要使用 <code>QEMU</code> 的图形界面形式才可以嗷。</p>


]]></content:encoded>
    </item>
    <item>
      <title>Python 天生支持多态</title>
      <link>https://blueberry-universe.cn/2022-10-15-00/</link>
      <guid>https://blueberry-universe.cn/2022-10-15-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">Python 天生支持多态</source>
      <description>Python 天生支持多态
哈喽 ~
你好啊，我是蓝莓 ：）
Python 是一个天生支持多态的编程语言，如果你曾经学过 Java 或 C++ ，那么你一定知道，如果想让一个变量既可以指向一个类的父类也能指向这个类本身，那么就要把这个变量定义成这个类的父类的类型才可以。但是，在 Python 中就简单多了，Python 是一门动态编程语言，不需要声明变...</description>
      <content:encoded><![CDATA[
<p>哈喽 ~</p>
<p>你好啊，我是蓝莓 ：）</p>
<p>Python 是一个天生支持多态的编程语言，如果你曾经学过 <code>Java</code> 或 <code>C++</code> ，那么你一定知道，如果想让一个变量既可以指向一个类的父类也能指向这个类本身，那么就要把这个变量定义成这个类的父类的类型才可以。但是，在 <code>Python</code> 中就简单多了，<code>Python</code> 是一门动态编程语言，不需要声明变量的类型就可以直接为它赋值，而这个变量是什么类型取决于你为它赋了一个什么样类型的值。</p>
<h2>1 给类起个新名字</h2>
<p>在  <code>Python</code>  中的变量可以理解为一个便利贴（标签），当你把一个值赋给一个变量的时候，就相当于你为这个值起了一个新的名字，你想对这个值的操作都可以用这个 <code>名字</code> 来表示。</p>
<p>这时候，你可以类比一下 <code>人</code>，当每个人出生到这个世界的时候是没有 <code>代号</code> 的，如果一个人没有代号，我们就不知道该怎么用语言来描述了，比如有一个婴儿刚出生在我们的面前。我们可以说让 <code>他</code> 喝牛奶。如果语言中都不存在代词这种东西的话，我们甚至无法来描述如何让这个刚出生的婴儿喝牛奶。这时候，我们可以为这个婴儿贴上几个标签，比如第一个标签是 <code>蓝莓</code> ，第二个标签是 <code>蓝宇</code>，第三个标签是 'blueberry'，这时候，这些标签的作用都是完全一样的。</p>
<ol>
<li>让 <code>蓝莓</code> 喝牛奶</li>
<li>让 <code>蓝宇</code> 喝牛奶</li>
<li>让 <code>blueberry</code> 喝牛奶</li>
</ol>
<p>这三句话表达的意思都是一样的，那么类比到 <code>Python</code> 中也是完全等同的，比如这个婴儿已经有了 <code>蓝莓</code> 这个标签，那么当我执行这样一个语句:</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">蓝宇 <span class="token operator">=</span> 蓝莓</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>执行完这条语句之后，我就为这个刚出生的婴儿起了一个新的名字，这个新名字叫 <code>蓝宇</code>，一定不要有任何偏见，虽然我们是用 <code>蓝莓</code> 这个标签赋值给了 <code>蓝宇</code>。但是要知道 <code>蓝莓</code> 对于这个婴儿而言也是一个普通的标签而已，只不过一开始我们就有了 <code>蓝莓</code> 这个标签，所以后续的操作都需要通过它来表达。可，现在情况不一样了，这个婴儿又多出来一个叫 <code>蓝宇</code> 的标签，现在这两个标签的同等级别的，没有什么高低之分，这两个标签都贴在了这个婴儿身上成为了这个婴儿的代号。</p>
<p><strong>看看编程中是什么情况</strong></p>
<p>比如当我创建一个名字叫 <code>Blueberry</code> 的类：</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Blueberry</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">say</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'I am blueberry 蓝莓'</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里的类名 <code>Blueberry</code> 就是这个客观存在的类的一个标签（名字），如果在这个类诞生的那一刻起就没有名字的话，我们甚至不知道该如何去操作它，所以在定义类的时候就先给它贴上这么一个标签 <code>Blueberry</code>。</p>
<p>好啦，这时候我再给它贴上一个新的标签 <code>BlueVerse</code>：</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">BlueVerse <span class="token operator">=</span> Blueberry</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>Blueberry</strong></p>
<p>对于刚诞生的这个客观存在的类而言，它拥有了两个标签，现在执行下边这段代码：</p>
<p>你可以看到它正常的输出了 <code>I am blueberry 蓝莓</code></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">blueberry <span class="token operator">=</span> Blueberry<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">blueberry<span class="token punctuation">.</span>say<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<p><strong>BlueVerse</strong></p>
<p>接着我们再执行这段代码：</p>
<p>你会发现，他们输出了同样的内容，不必多说，相信聪明的你看到这里一定就明白啦！</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">BlueVerse <span class="token operator">=</span> Blueberry</span>
<span class="line">blue_verse <span class="token operator">=</span> BlueVerse<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">blue_verse<span class="token punctuation">.</span>say<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<h2>2 更有趣的玩儿法</h2>
<p>那么，看到了上边的内容后，就可以有很多的想象空间了，比如我们可以像下边这样玩儿一下：</p>
<p>其实，我特别喜欢 《名侦探柯南》 里边的黑帮大佬：琴酒（Gin），也特别喜欢 灰原哀（Haibara Ai）。在这里定义了三个类，分别是 <code>Blueberry</code> , <code>HaibaraAi</code>, <code>Gin</code>，这三个类中都包含着一个名字相同的 <code>成员函数</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">class Blueberry:</span>
<span class="line">    def say(self):</span>
<span class="line">        print('I am blueberry 蓝莓')</span>
<span class="line"></span>
<span class="line">class HaibaraAi:</span>
<span class="line">    def say(self):</span>
<span class="line">        print('I am Haibara Ai 灰原哀')</span>
<span class="line">        </span>
<span class="line">class Gin:</span>
<span class="line">    def say(self):</span>
<span class="line">        print('I am Gin 琴酒')</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接着我给这三个类分别起个别名：</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">members <span class="token operator">=</span> <span class="token punctuation">[</span>Blueberry<span class="token punctuation">,</span> HaibaraAi<span class="token punctuation">,</span> Gin<span class="token punctuation">]</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你看到了嘛，这里用的是列表给他们起别名，其实都是一样的，比如 <code>members[0]</code> 也是一个变量嘛，<code>members[0]</code> 就是 <code>Blueberry</code> 的别名。</p>
<p>接着再执行这段代码：</p>
<p>遍历每一个类，然后实例化它，再调用实例对象的 <code>say</code> 方法，不必多说，相信聪明的你也明白这里啦！</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">for</span> member <span class="token keyword">in</span> members<span class="token punctuation">:</span></span>
<span class="line">    obj <span class="token operator">=</span> member<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    obj<span class="token punctuation">.</span>say<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<p>今天就分享这么多啦 ~</p>
<p>如果你看到了这里 ~</p>
<p>给我点个赞叭 ~ 谢谢你的支持哇 ~</p>


]]></content:encoded>
    </item>
    <item>
      <title>Python 函数天生带有暂停键</title>
      <link>https://blueberry-universe.cn/2022-12-06-00/</link>
      <guid>https://blueberry-universe.cn/2022-12-06-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">Python 函数天生带有暂停键</source>
      <description>Python 函数天生带有暂停键
Python 生成器函数
在很多编程语言中的函数都是被调用之后就一气呵成的执行到底，知道这个函数执行 return 之后，它的使命也就结束了，然而 Python 中的函数有一个更有趣的特性，与其说是函数，不如把它叫做 生成器
普通的函数
定义一个函数，这个函数的功能就是返回 斐波那契 数列的前 $n$ 个元素的值，那么...</description>
      <content:encoded><![CDATA[
<h2>Python 生成器函数</h2>
<p>在很多编程语言中的函数都是被调用之后就一气呵成的执行到底，知道这个函数执行 <code>return</code> 之后，它的使命也就结束了，然而 <code>Python</code> 中的函数有一个更有趣的特性，与其说是函数，不如把它叫做 <code>生成器</code></p>
<h2>普通的函数</h2>
<p>定义一个函数，这个函数的功能就是返回 <code>斐波那契</code> 数列的前 $n$ 个元素的值，那么我选择使用一个列表返回这些元素，对于这个函数而言有一个缺点就是，如果 $n$ 的值非常大的话，那就需要等待这个函数把所有的前 $n$ 个值全部计算完成后才能返回</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">fib</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    a<span class="token punctuation">,</span> b <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span></span>
<span class="line">    <span class="token keyword">if</span> n <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span></span>
<span class="line">    <span class="token keyword">if</span> n <span class="token operator">==</span> <span class="token number">2</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span></span>
<span class="line"></span>
<span class="line">    res <span class="token operator">=</span> <span class="token punctuation">[</span>a<span class="token punctuation">,</span> b<span class="token punctuation">]</span></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        a<span class="token punctuation">,</span> b <span class="token operator">=</span> b<span class="token punctuation">,</span> a<span class="token operator">+</span>b</span>
<span class="line">        res<span class="token punctuation">.</span>append<span class="token punctuation">(</span>b<span class="token punctuation">)</span></span>
<span class="line">    </span>
<span class="line">    <span class="token keyword">return</span> res</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在这儿看一下这个函数的使用效果，你可以看到这个函数能够函数好的完成这个任务，如果我在做一件事情的时候并不需要它把所有的数据都计算出来一起返回给我，而是我使用一个它就计算一个出来，待我需要使用下一个的时候，它再把下一个数值返回给我，这样就能够同时兼顾生产数据和消费数据了。</p>
<p></p>
<h2>生成器函数</h2>
<p>那么，生成器函数应运而生，顾名思义 <code>生成器</code> 就是生产者，是用来生产数据的</p>
<p>创建生成器函数关键在于使用 <code>yield</code> 关键字替换 <code>return</code> ，其中 <code>yield</code> 的作用与 <code>return</code> 十分相似，但是也有一些区别</p>
<p>创建一个最简单的生成器函数，通过下边这段代码，我就创建了一个名字叫做 <code>example</code> 的生成器对象。现在你发现了，使用函数的方式竟然就像使用 <code>类</code> 一样，<code>generator_example()</code> 不再是简简单单的调用函数并执行里边的代码，而是通过 <code>generator_example()</code> 创建了一个生成器 <code>对象</code>。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">generator_example</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token string">'hello world'</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token string">'I am blueberry'</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token string">'I want to help you to become better :)'</span></span>
<span class="line">    </span>
<span class="line">example <span class="token operator">=</span> generator_example<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>生成器对象 <code>example</code> 是可以被迭代的，是可以被遍历的，那么就让我们使用 <code>for</code> 语句来遍历一下：</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">for</span> each <span class="token keyword">in</span> example<span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">print</span><span class="token punctuation">(</span>each<span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<p>你看到，这三个字符串都被输出出来了！</p>
<p>那么如何来证明，这个生成器是一次计算一个数值而不是把所有的数值都计算出来的呢？</p>
<p>我对上边的生成器函数做一个简单的修改：</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">generator_example</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'输出了第 1 个字符串'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token string">'hello world'</span></span>
<span class="line">    </span>
<span class="line">    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'输出了第 2 个字符串'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token string">'I am blueberry'</span></span>
<span class="line">    </span>
<span class="line">    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'输出了第 1 个字符串'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token string">'I want to help you to become better :)'</span></span>
<span class="line"></span>
<span class="line">example <span class="token operator">=</span> generator_example<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这时，我通过 <code>next</code> 函数来遍历生成器的内容，如果你不理解 <code>next</code> 函数的话。联想下 <code>for</code> 语句遍历数据，在你使用 <code>for</code> 遍历一个可迭代类型对象的时候，你不能让它遍历到一个数值后停下来，一旦停下来这一轮的遍历就结束了。</p>
<p>如果你使用 <code>next</code> 的话，可以一次只遍历出来一个值，下一次的时候接着上一个值进行迭代</p>
<p>在生成器 <code>generator_example</code> 中我放了几个 <code>print</code> 语句，通过下边的输出，你可以发现，<code>yield</code> 出去 <code>s1</code> 后并没有执行这条 <code>yield</code> 语句下边的 <code>print</code> 语句，这就说明了此时生成器被暂停下来了！</p>
<p></p>
<p>是不是很有趣 ？</p>
<p>最后再使用生成器实现一下斐波那契数列：</p>
<p><strong>生成器实现斐波那契</strong></p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">fib_generator</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">assert</span> n <span class="token operator">>=</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token string">'n 应大于等于 3'</span></span>
<span class="line">    </span>
<span class="line">    <span class="token keyword">yield</span> <span class="token number">1</span></span>
<span class="line">    <span class="token keyword">yield</span> <span class="token number">1</span></span>
<span class="line"></span>
<span class="line">    a<span class="token punctuation">,</span> b <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span></span>
<span class="line">    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> n<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        a<span class="token punctuation">,</span> b <span class="token operator">=</span> b<span class="token punctuation">,</span> a<span class="token operator">+</span>b</span>
<span class="line">        <span class="token keyword">yield</span> b</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">for each in fib_generator(9):</span>
<span class="line">    print(each, end=', ')</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p></p>


]]></content:encoded>
    </item>
    <item>
      <title>彻底理解 Python 装饰器</title>
      <link>https://blueberry-universe.cn/2023-02-08-00/</link>
      <guid>https://blueberry-universe.cn/2023-02-08-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">彻底理解 Python 装饰器</source>
      <description>彻底理解 Python 装饰器
在 Python 中有一个很有趣的语言特性是装饰器。
假象这样一个场景：你写了一个函数，当你完成了这个函数的功能后，你希望这个函数在每次运行的时候都能记录下来自己的调用时间或者运行时间到一个指定的地方存储下来，或者就是非常简单的，在每次运行完成一个函数后把自己的运行时间给输出出来。
相信聪明的你，一定知道了应该如何完成这...</description>
      <content:encoded><![CDATA[
<p>在 Python 中有一个很有趣的语言特性是装饰器。</p>
<p>假象这样一个场景：你写了一个函数，当你完成了这个函数的功能后，你希望这个函数在每次运行的时候都能记录下来自己的调用时间或者运行时间到一个指定的地方存储下来，或者就是非常简单的，在每次运行完成一个函数后把自己的运行时间给输出出来。</p>
<p>相信聪明的你，一定知道了应该如何完成这个操作，我们先来看看用最简单的方法要怎么来完成。</p>
<h2>1 先随便写个函数吧</h2>
<p>就写一个最简单的函数好啦，乘方运算。</p>
<p>计算 <code>a</code> 的 <code>b</code> 次方。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">blueberry_pow</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">return</span> a <span class="token operator">**</span> b</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>让我运行一下：</p>
<p></p>
<h2>2 计算函数运行时长</h2>
<p>可以直接这样写，使用 <code>time.time()</code> 分别记录 <code>blueberry_pow</code> 函数运行前的时间点 <code>start</code> 和运行结束后的时间点 <code>end</code>。最后用结束时间 <code>end</code> 减去 开始时间 <code>start</code> 就是 <code>blueberry_pow</code> 函数的运行时长 <code>run_time</code> 了。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">import</span> time</span>
<span class="line"></span>
<span class="line">start <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">blueberry_pow<span class="token punctuation">(</span><span class="token number">1000000</span><span class="token punctuation">,</span> <span class="token number">1000000</span><span class="token punctuation">)</span></span>
<span class="line">end <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">run_time <span class="token operator">=</span> end <span class="token operator">-</span> start</span>
<span class="line"></span>
<span class="line"><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'blueberry_pow 的运行时长是: '</span><span class="token punctuation">,</span> run_time<span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<h2>3 浅包装一下</h2>
<p>聪明的你一定会觉得这个方法真是太简单了！可是 <code>Python</code> 这门编程语言一直都非常讲究 <code>优雅</code> 二字，毕竟人家的官方文档介绍中都说自己非常的 <code>elegant</code> 呢！这怕是最 自恋的 编程语言了吧！</p>
<p></p>
<p>我们知道在 <code>Python</code> 中一切皆对象，那么函数本身也是个对象，我们可以直接把函数 <code>blueberry_pow</code> 赋值给变量，甚至当做参数进行传递。</p>
<p>那么，第一种写法就有了，我们专门写一个记时用的函数，然后把 <code>blueberry_pow</code> 当做参数传递给这个记时函数，在这里边运行。</p>
<p>第 1 个参数 <code>func</code> 是传递了需要被记录时间的函数，其后的第 2 个参数 <code>args</code> 和 第 3 个参数 <code>kwargs</code> 如果你学习过函数的参数传递方式相关的内容的话，一定见过这样的写法。在这里就不展开细聊这种参数传递方法了。总之，你知道的我们传递给 <code>timer</code> 的第 2 个参数开始的值都被我们按照同样的方式传递给了 <code>func</code> 所代表的函数就好啦。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">timer</span><span class="token punctuation">(</span>func<span class="token punctuation">,</span> <span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    start <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    res <span class="token operator">=</span> func<span class="token punctuation">(</span><span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span></span>
<span class="line">    end <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">    run_time <span class="token operator">=</span> end <span class="token operator">-</span> start</span>
<span class="line">    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'blueberry_pow 的运行时长是: '</span><span class="token punctuation">,</span> run_time<span class="token punctuation">)</span></span>
<span class="line">    </span>
<span class="line">    <span class="token keyword">return</span> res</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">res <span class="token operator">=</span> timer<span class="token punctuation">(</span>blueberry_pow<span class="token punctuation">,</span> <span class="token number">100000</span><span class="token punctuation">,</span> <span class="token number">666666</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接着让我们来使用 <code>timer</code> 函数对<code>blueberry_pow</code> 函数记个时，你会发现，同样可以完成这个人物。</p>
<p></p>
<h2>4 再进一步包装</h2>
<p>有了第 3 部分的方法后，可以使用 <code>timer</code> 工具函数对它进行记时。</p>
<p>我们能不能直接在 <code>blueberry_pow</code> 的基础上创造一个新的函数，让这个新的函数增加上一个记录时间的功能呢？</p>
<p>当然啦，我们可以这样来写。</p>
<p>顾名思义 <code>add_timer</code> 就是要为 <code>func</code> 函数添加一个 <code>timer</code> 的功能。让我们来看看在 <code>add_timer</code> 中做了什么呢？</p>
<p>你可以发现，我们在函数的内部定义了一个函数 <code>new_func</code> 然后我们在 <code>new_func</code> 函数中不仅运行了 <code>func</code> 函数，而且还运行了一些我们希望添加的记时功能。最后我们把定义好的 <code>new_func</code> 函数作为 <code>add_timer</code> 函数的返回值返回出去。这样一来，我们就可以为任意的函数 <code>func</code> 添加上记时功能了。</p>
<p>在这里，我们为 <code>blueberry_pow</code> 函数添加计时功能，并且将 <code>add_timer</code> 函数返回出去的函数起个名字叫 <code>new_blueberry_pow</code> 。接着我们调用 <code>new_blueberry_pow</code> 函数的时候就像是调用 <code>blueberry_pow</code> 函数一样的使用方法即可。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">add_timer</span><span class="token punctuation">(</span>func<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">new_func</span><span class="token punctuation">(</span><span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        start <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">        res <span class="token operator">=</span> func<span class="token punctuation">(</span><span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span></span>
<span class="line">        end <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">        run_time <span class="token operator">=</span> end <span class="token operator">-</span> start</span>
<span class="line">        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'blueberry_pow 的运行时长是: '</span><span class="token punctuation">,</span> run_time<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> new_func</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">new_blueberry_pow = add_timer(blueberry_pow)</span>
<span class="line">res = new_blueberry_pow(100000, 666666)</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<h2>5 优雅的装饰器</h2>
<p>在第 4 部分中，我们看到了，可以使用这样的方式来在 <code>blueberry_pow</code> 的基础上创建一个新的函数，让这个新的函数拥有计时功能。</p>
<p>那么在第 4 部分中唯一不足的地方就是这个过程看起来还是不够优雅，并且我们创建出来的新的函数 <code>new_blueberry_pow</code> 的名字相较于 <code>blueberry_pow</code> 的函数名字发生了变化，然而这个变化其实是多余的。</p>
<p>另外，<code>new_blueberry_pow = add_timer(blueberry_pow)</code> 这一行代码看起来也实在是多余。</p>
<p>害！人家 <code>Python</code> 可是一门儿自称是非常 <code>elegant</code> 的一门编程语言，自然对这一点有了原生的语言特性作为支持。</p>
<p>那就是装饰器啦！</p>
<p>让我们把代码重新来一遍，定义装饰器，其实就是在定义一个像第 4 部分中 <code>add_timer</code> 一样的函数而已。</p>
<p><strong>定义装饰器 timer</strong></p>
<p>哈哈，你发现了，<code>timer</code> 函数和第 4 部分中的 <code>add_timer</code> 函数中的内容长的一模一样！我只是给它改了个名字而已。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">def</span> <span class="token function">timer</span><span class="token punctuation">(</span>func<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">new_func</span><span class="token punctuation">(</span><span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        start <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">        res <span class="token operator">=</span> func<span class="token punctuation">(</span><span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span></span>
<span class="line">        end <span class="token operator">=</span> time<span class="token punctuation">.</span>time<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">        run_time <span class="token operator">=</span> end <span class="token operator">-</span> start</span>
<span class="line">        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'blueberry_pow 的运行时长是: '</span><span class="token punctuation">,</span> run_time<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> new_func</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>定义乘方运算函数</strong></p>
<p>接着！让我们来定义一个 <code>蓝莓</code> 专用的乘方运算函数 <code>blueberry_pow</code> ， 哈哈 ~</p>
<p>你会发现在函数定义的上边一行多了一个 <code>@timer</code>，这就是把 <code>timer</code> 装饰器用在 <code>blueberry_pow</code> 函数上。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token decorator annotation punctuation">@timer</span></span>
<span class="line"><span class="token keyword">def</span> <span class="token function">blueberry_pow</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">return</span> a <span class="token operator">**</span> b</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这时候让我们调用一下<code>blueberry_pow</code> 函数，看看会发生什么呢？</p>
<p></p>
<p>哇偶！是不是很神奇？我们直接调用 <code>blueberry_pow</code> 函数就直接拥有了计时功能了！</p>
<p>哈哈，那么这个实现原理就和第 4 部分中所说到的 <code>add_timer</code> 函数的工作原理是完全一样的！</p>
<p>只不过在第 5 部分中我为 <code>add_timer</code> 函数改了个名字改成了 <code>timer</code> 函数并且在定义 <code>blueberry_pow</code> 函数的时候，在其上方写了一个 <code>@timer</code>。那么<code>@timer</code>的作用就是说，当你在调用<code>blueberry_pow</code>函数的时候，你先把<code>blueberry_pow</code>函数丢给<code>timer</code>函数，然后<code>timer</code>函数会返回一个新的函数<code>new_func</code>，这时候在接受<code>timer</code>函数的返回值的时候把它赋值给<code>blueberry_pow</code>这个标签。</p>
<p>经过这样的一番折腾后，我们的<code>blueberry_pow</code>函数就得到了<code>装饰</code>，得到了一些改造。</p>


]]></content:encoded>
    </item>
    <item>
      <title>彻底理解 Python 万物皆对象</title>
      <link>https://blueberry-universe.cn/2023-02-15-00/</link>
      <guid>https://blueberry-universe.cn/2023-02-15-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">彻底理解 Python 万物皆对象</source>
      <description>彻底理解 Python 万物皆对象
在 Python 中的一切内容都是以对象的形式存在的。
自定义的类本身是一个对象（类对象），通过类对象实例化的东西也是一个对象（实例对象）。甚至创建出的一个浮点数也是一个对象（浮点对象）。
当我们在 Python 中写出这样的代码时，你会不会感到奇怪？

如果你已经使用了很久一段时间 Python 的话，对这个操作是...</description>
      <content:encoded><![CDATA[
<p>在 Python 中的一切内容都是以对象的形式存在的。</p>
<p>自定义的类本身是一个对象（类对象），通过类对象实例化的东西也是一个对象（实例对象）。甚至创建出的一个浮点数也是一个对象（浮点对象）。</p>
<p>当我们在 Python 中写出这样的代码时，你会不会感到奇怪？</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line">a <span class="token operator">=</span> <span class="token builtin">float</span><span class="token punctuation">(</span><span class="token number">6.66</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你已经使用了很久一段时间 Python 的话，对这个操作是非常熟悉的。一直都在强调，万物皆对象，那么创建浮点类型实例对象的对象就是 <code>float</code> 对象，按理来说 <code>float</code> 是一个对象，可是它竟然可以被调用？一个对象竟然可以像函数一样被调用啊！</p>
<p>可以被调用的对象称为 <code>可调用对象</code>，对于内建对象 <code>float</code> 而言，在实现 <code>CPython</code> 的时候肯定是事先就被写好了这个被调用后所执行的逻辑了。那么对于我们自己创建类所生成的实例对象同样可以完成诸如这样的魔法操作。</p>
<p>在我的这篇文章中有提到过，这类看上去非常神奇的内容是如何实现的，如果希望一个对象可以被调用，那么我们就实现 <code>__call__</code> 魔法函数即可。</p>
<p>可参考这篇文章：</p>
<p>【遇见 Python 魔法函数】</p>
<p>在这儿，简单体会一下 <code>__call__</code> 魔法函数的使用</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token keyword">class</span> <span class="token class-name">Blueberry</span><span class="token punctuation">:</span></span>
<span class="line">    <span class="token keyword">def</span> <span class="token function">__call__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span></span>
<span class="line">        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'hello world, I am blueberry'</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">blueberry <span class="token operator">=</span> Blueberry<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">blueberry<span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>我们只需要实现 <code>__call__</code> 方法，随后在调用 <code>blueberry</code> 对象的时候就会执行实现定义好的 <code>__call__</code> 函数里的代码了</p>
<p></p>
<h2>考察浮点数值对象</h2>
<p>我们就通过最简单的浮点类型的对象深入理解 Python 中万物皆对象是如何实现的。</p>
<p>在 <code>Python</code> 中有两个非常特别的 <code>对象</code> 分别是 <code>type</code> 和 <code>object</code>。其中 <code>type</code> 是类型对象，另外所有的对象的基类都是 <code>object</code>，也就是说在继承链的最顶端一定是 <code>object</code> 对象。</p>
<p><strong>内建对象的基类</strong></p>
<p>我们先看看内建对象 <code>float</code> 的基类是谁，通过如下的代码，我们可以发现 <code>float</code> 对象是继承自 <code>object</code> 对象的，证明了内建对象继承自 <code>object</code>。其中通过查看 <code>float</code> 的 <code>__mro__</code> 属性可以看到一个对象的继承链。两种方式都验证了这一点。</p>
<div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token builtin">isinstance</span><span class="token punctuation">(</span><span class="token builtin">float</span><span class="token punctuation">,</span> <span class="token builtin">object</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><div class="language-python line-numbers-mode" data-highlighter="prismjs" data-ext="py"><pre><code class="language-python"><span class="line"><span class="token builtin">float</span><span class="token punctuation">.</span>__mro__</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p><strong>内建类型的类型</strong></p>
<p>查看 <code>float</code> 的类型，通过以下两种方式都是可以查看一个对象对应的 <code>type</code> 的。</p>


]]></content:encoded>
    </item>
    <item>
      <title></title>
      <link>https://blueberry-universe.cn/2024-05-11-00/</link>
      <guid>https://blueberry-universe.cn/2024-05-11-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml"></source>
      <description>一文总结 Go 语言语法
目录：

变量定义
常量和枚举
条件语句
循环语句
函数定义
指针
内建容器：array （数组）
内建容易：slice （切片）
内建容器：map
Go 面向 “对象”
Go 的包
Interface 接口
Goroutine 并发编程
Channel 通道

1 变量定义
变量的初始值
在 go 语言中，每个变量都有初值，...</description>
      <content:encoded><![CDATA[<h2>一文总结 Go 语言语法</h2>
<p><strong>目录：</strong></p>
<ol>
<li>变量定义</li>
<li>常量和枚举</li>
<li>条件语句</li>
<li>循环语句</li>
<li>函数定义</li>
<li>指针</li>
<li>内建容器：array （数组）</li>
<li>内建容易：slice （切片）</li>
<li>内建容器：map</li>
<li>Go 面向 “对象”</li>
<li>Go 的包</li>
<li>Interface 接口</li>
<li>Goroutine 并发编程</li>
<li>Channel 通道</li>
</ol>
<h2>1 变量定义</h2>
<p><strong>变量的初始值</strong></p>
<p>在 go 语言中，每个变量都有初值，整型变量 a 的初始值是 <code>0</code>，字符串变量的初始值是空串 <code>&quot;&quot;</code></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">variableZeroValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> a <span class="token builtin">int</span>  <span class="token comment">// 直接定义一个变量出来</span></span>
<span class="line">	<span class="token keyword">var</span> s <span class="token builtin">string</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"variable a: %d \n"</span><span class="token punctuation">,</span> a<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"variable s: %q \n"</span><span class="token punctuation">,</span> s<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">variable a: 0 </span>
<span class="line">variable s: "" </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>手动赋值</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">variableInitialValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> a<span class="token punctuation">,</span> b <span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span> <span class="token comment">// 定义的时候还可以赋初值</span></span>
<span class="line">	<span class="token keyword">var</span> s <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"hello world."</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> s<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">1 2 hello world.</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>类型推断</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">variableInitialValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">var</span> a<span class="token punctuation">,</span> b <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span> <span class="token comment">// 可以省略类型</span></span>
<span class="line">   	<span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token string">"hello world."</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> s<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">1 2 hello world.</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>更简洁的类型推断写法</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">variableShorter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> s <span class="token operator">:=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">"hello world."</span> <span class="token comment">// 多个类型的是可以放在一起写的；并且在定义的时候写冒号就可以了 var 都可以省略</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> s<span class="token punctuation">)</span></span>
<span class="line">    </span>
<span class="line">    b <span class="token operator">=</span> <span class="token number">666</span> <span class="token comment">// 第二次再用它的时候就不用写冒号咯</span></span>
<span class="line">    fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">1 2 hello world.</span>
<span class="line">666</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>函数体外定义变量（包内变量）</strong></p>
<p>定义包级别的变量必须使用关键字开始，而不能使用冒号的形式定义变量</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">666</span> <span class="token comment">// 在函数外面定义变量的时候必须使用 var 来定义，也是可以推断出来的</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 还可以一次定义多个变量</span></span>
<span class="line"><span class="token keyword">var</span> <span class="token punctuation">(</span></span>
<span class="line">	aa <span class="token operator">=</span> <span class="token number">111</span></span>
<span class="line">	bb <span class="token operator">=</span> <span class="token number">222</span></span>
<span class="line">	cc <span class="token operator">=</span> <span class="token number">333</span></span>
<span class="line"><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>内置变量的类型</strong></p>
<p><code>complex</code> 代表复数</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token builtin">bool</span><span class="token punctuation">,</span> <span class="token builtin">string</span></span>
<span class="line"><span class="token punctuation">(</span>u<span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>u<span class="token punctuation">)</span><span class="token builtin">int8</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>u<span class="token punctuation">)</span><span class="token builtin">int16</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>u<span class="token punctuation">)</span><span class="token builtin">int32</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>u<span class="token punctuation">)</span><span class="token builtin">int64</span><span class="token punctuation">,</span> <span class="token builtin">uintptr</span></span>
<span class="line"><span class="token builtin">byte</span><span class="token punctuation">,</span> <span class="token builtin">rune</span></span>
<span class="line"><span class="token builtin">float32</span><span class="token punctuation">,</span> <span class="token builtin">float64</span><span class="token punctuation">,</span> <span class="token builtin">complex64</span><span class="token punctuation">,</span> <span class="token builtin">complex128</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>类型转换是强制的</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">triangle</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> a<span class="token punctuation">,</span> b <span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span></span>
<span class="line">	<span class="token keyword">var</span> c <span class="token builtin">int</span></span>
<span class="line">	c <span class="token operator">=</span> <span class="token function">int</span><span class="token punctuation">(</span>math<span class="token punctuation">.</span><span class="token function">Sqrt</span><span class="token punctuation">(</span><span class="token function">float64</span><span class="token punctuation">(</span>a<span class="token operator">*</span>a <span class="token operator">+</span> b<span class="token operator">*</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 因为 Sqrt 接收的是浮点数，所以你必须显示的进行转换而不会自动转换</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> c<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">3 4 5</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2>2 常量和枚举</h2>
<p><strong>普通常量的定义</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">constant</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">const</span> filename <span class="token operator">=</span> <span class="token string">"helloworld.txt"</span></span>
<span class="line">	<span class="token keyword">const</span> a<span class="token punctuation">,</span> b <span class="token operator">=</span> <span class="token number">666</span><span class="token punctuation">,</span> <span class="token number">999</span></span>
<span class="line">	<span class="token keyword">var</span> c <span class="token builtin">int</span></span>
<span class="line">	c <span class="token operator">=</span> <span class="token function">int</span><span class="token punctuation">(</span>math<span class="token punctuation">.</span><span class="token function">Sqrt</span><span class="token punctuation">(</span>a<span class="token operator">*</span>a <span class="token operator">+</span> b<span class="token operator">*</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 常量相当于文本替换</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> c<span class="token punctuation">)</span></span>
<span class="line">    </span>
<span class="line">    <span class="token comment">// 定义一组常量</span></span>
<span class="line">    <span class="token keyword">const</span> <span class="token punctuation">(</span></span>
<span class="line">		c1 <span class="token operator">=</span> <span class="token number">111</span></span>
<span class="line">		c2 <span class="token operator">=</span> <span class="token number">222</span></span>
<span class="line">	<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>c1<span class="token punctuation">,</span> c2<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 也可以定义为包内的常量，则包内部的函数都可以使用</span></span>
<span class="line"></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">helloworld.txt 1200</span>
<span class="line">111 222</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>枚举类型</strong></p>
<p><code>iota</code> 代表这个常量列表是自增值，使用下划线代表不使用这个位置的值</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">enums</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">const</span> <span class="token punctuation">(</span></span>
<span class="line">		cpp <span class="token operator">=</span> <span class="token boolean">iota</span> <span class="token comment">// iota 代表从 0 开始, 并且后面的都是在 iota 的基础上自增 1 的</span></span>
<span class="line">		<span class="token boolean">_</span> <span class="token comment">// 这里相当于 1，用下划线代表不用这个 1 了</span></span>
<span class="line">		python <span class="token comment">// 这里相当于 2</span></span>
<span class="line">	<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// b, kb, mb, gb, tb, pb</span></span>
<span class="line">	<span class="token keyword">const</span> <span class="token punctuation">(</span></span>
<span class="line">		b <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator">&lt;&lt;</span> <span class="token punctuation">(</span><span class="token number">10</span> <span class="token operator">*</span> <span class="token boolean">iota</span><span class="token punctuation">)</span> <span class="token comment">// 你甚至还可以写成表达式 相当于是：1 &lt;&lt; (10 * 0)</span></span>
<span class="line">		kb <span class="token comment">// 这里相当于 1 &lt;&lt; (10 * 1)</span></span>
<span class="line">		mb <span class="token comment">// 这里相当于 1 &lt;&lt; (10 * 2)</span></span>
<span class="line">		gb <span class="token comment">// 后面以此类推</span></span>
<span class="line">		tb</span>
<span class="line">		pb</span>
<span class="line">	<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>cpp<span class="token punctuation">,</span> python<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">,</span> kb<span class="token punctuation">,</span> mb<span class="token punctuation">,</span> gb<span class="token punctuation">,</span> tb<span class="token punctuation">,</span> pb<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">0 2</span>
<span class="line">1 1024 1048576 1073741824 1099511627776 1125899906842624</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h2>3 条件语句</h2>
<p><strong>普通的条件判断</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">bounded</span><span class="token punctuation">(</span>v <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">if</span> v <span class="token operator">></span> <span class="token number">100</span> <span class="token punctuation">{</span> <span class="token comment">// 条件语句不用写圆括号</span></span>
<span class="line">		<span class="token keyword">return</span> <span class="token number">100</span></span>
<span class="line">	<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> v <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token keyword">return</span> <span class="token number">0</span></span>
<span class="line">	<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token keyword">return</span> v</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>带分号的 if</strong></p>
<p>先运行前半句，然后才执行 <code>err</code> 是否为空的判断，这里的 contents 是属于 <code>if</code> 语句这个作用域的</p>
<p>在条件语句中 <code>||</code> 表示两个条件之间的或运算，<code>&amp;&amp;</code> 表示两个条件之间的与运算</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">const</span> filename <span class="token operator">=</span> <span class="token string">"hello.txt"</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// 这里代表先执行分号前面的语句，然后再判断分号后面的语句是否为 true</span></span>
<span class="line">    <span class="token comment">// 并且 contents 和 err 都是if语句局部的量</span></span>
<span class="line">	<span class="token keyword">if</span> contents<span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">ReadFile</span><span class="token punctuation">(</span>filename<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"%s \n"</span><span class="token punctuation">,</span> contents<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">hello</span>
<span class="line">world. </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>switch 语句</strong></p>
<p>每一个 case 后面默认带有 <code>break</code> 的功能</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">eval</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">,</span> op <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> result <span class="token builtin">int</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// op 和某一个 case 后面的值相等 则执行相应的 case 里面的内容</span></span>
<span class="line">    <span class="token comment">// 每个 case 执行完成后自动 break 出去</span></span>
<span class="line">	<span class="token keyword">switch</span> op <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"+"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">+</span> b</span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"-"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">-</span> b</span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"*"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">*</span> b</span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"/"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">/</span> b</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line">	<span class="token keyword">return</span> result</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// switch 语句可以有 default 分支</span></span>
<span class="line"><span class="token comment">// panic 用于停止程序的运行</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">grade</span><span class="token punctuation">(</span>score <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span></span>
<span class="line">	g <span class="token operator">:=</span> <span class="token string">""</span></span>
<span class="line">	<span class="token keyword">switch</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">case</span> score <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token operator">||</span> score <span class="token operator">></span> <span class="token number">100</span><span class="token punctuation">:</span></span>
<span class="line">		<span class="token function">panic</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"Wrong score: %d"</span><span class="token punctuation">,</span> score<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token keyword">case</span> score <span class="token operator">&lt;</span> <span class="token number">60</span><span class="token punctuation">:</span></span>
<span class="line">		g <span class="token operator">=</span> <span class="token string">"F"</span></span>
<span class="line">	<span class="token keyword">case</span> score <span class="token operator">&lt;</span> <span class="token number">80</span><span class="token punctuation">:</span></span>
<span class="line">		g <span class="token operator">=</span> <span class="token string">"C"</span></span>
<span class="line">	<span class="token keyword">case</span> score <span class="token operator">&lt;</span> <span class="token number">90</span><span class="token punctuation">:</span></span>
<span class="line">		g <span class="token operator">=</span> <span class="token string">"B"</span></span>
<span class="line">	<span class="token keyword">case</span> score <span class="token operator">&lt;=</span> <span class="token number">100</span><span class="token punctuation">:</span></span>
<span class="line">		g <span class="token operator">=</span> <span class="token string">"A"</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line">	<span class="token keyword">return</span> g</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>4 循环语句</h2>
<p><strong>for 循环</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    </span>
<span class="line">    <span class="token comment">// 1</span></span>
<span class="line">	sum <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator">&lt;=</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> <span class="token comment">// 同理不需要圆括号</span></span>
<span class="line">		sum <span class="token operator">+=</span> i</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>sum<span class="token punctuation">)</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// 2</span></span>
<span class="line">	sum2 <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">	i <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line">	<span class="token keyword">for</span> <span class="token punctuation">;</span> i <span class="token operator">&lt;=</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> <span class="token comment">// 可以不写 第一个分号前面的内容</span></span>
<span class="line">		sum2 <span class="token operator">+=</span> i</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>sum2<span class="token punctuation">)</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// 3</span></span>
<span class="line">	sum3 <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">	i <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">&lt;=</span> <span class="token number">100</span> <span class="token punctuation">{</span> <span class="token comment">// 这就相当于其他那些常见语言中的 while 循环了</span></span>
<span class="line">		sum3 <span class="token operator">+=</span> i</span>
<span class="line">		i<span class="token operator">++</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line">    </span>
<span class="line">    <span class="token comment">// 4 死循环</span></span>
<span class="line">    <span class="token keyword">for</span> <span class="token punctuation">{</span> <span class="token comment">// 这个直接代表死循环，相当于常见语言的 while(true)</span></span>
<span class="line">        <span class="token comment">// TODO 	</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>sum3<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>5 函数定义</h2>
<p><strong>定义函数和返回值</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token comment">// 返回值类型写在圆括号后面</span></span>
<span class="line"><span class="token comment">// 如果有多个返回值</span></span>
<span class="line"><span class="token comment">// 返回值类型要用圆括号包裹起来 (int, int) 代表返回两个 int 类型的返回值</span></span>
<span class="line"><span class="token comment">// 一般情况下, golang 中第一个返回数据，第二个返回值一般定义为 error 类型</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">eval</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">,</span> op <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> result <span class="token builtin">int</span></span>
<span class="line">	</span>
<span class="line">	<span class="token keyword">switch</span> op <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"+"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">+</span> b</span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"-"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">-</span> b</span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"*"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">*</span> b</span>
<span class="line">	<span class="token keyword">case</span> <span class="token string">"/"</span><span class="token punctuation">:</span></span>
<span class="line">		result <span class="token operator">=</span> a <span class="token operator">/</span> b</span>
<span class="line">	<span class="token keyword">default</span><span class="token punctuation">:</span> <span class="token comment">// switch 语句是可以有 default 的</span></span>
<span class="line">		<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"unsupported operation"</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">return</span> result<span class="token punctuation">,</span> <span class="token boolean">nil</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>函数也是一等公民</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">div</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> a <span class="token operator">/</span> b</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">apply</span><span class="token punctuation">(</span>op <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">,</span> a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	p <span class="token operator">:=</span> reflect<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>op<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">	opName <span class="token operator">:=</span> runtime<span class="token punctuation">.</span><span class="token function">FuncForPC</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"Calling function %s with args "</span><span class="token operator">+</span><span class="token string">"(%d, %d)\n"</span><span class="token punctuation">,</span> opName<span class="token punctuation">,</span> a<span class="token punctuation">,</span> b<span class="token punctuation">)</span></span>
<span class="line">	<span class="token keyword">return</span> <span class="token function">op</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// div 这个函数本身也可以被当做参数传递</span></span>
<span class="line">	res <span class="token operator">:=</span> <span class="token function">apply</span><span class="token punctuation">(</span>div<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>oputputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">Calling function main.div with args (10, 2)</span>
<span class="line">5</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>匿名函数</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 定义一个匿名函数传递给刚才的 apply 函数也是可以的</span></span>
<span class="line">	res <span class="token operator">:=</span> <span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token keyword">return</span> a <span class="token operator">/</span> b</span>
<span class="line">	<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>可变参数列表</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token comment">// 直接写 ... 就代表你可以传递任意个 int 类型的数值进来</span></span>
<span class="line"><span class="token comment">// 我们可以遍历 nums 获取值</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">sum</span><span class="token punctuation">(</span>nums <span class="token operator">...</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	s <span class="token operator">:=</span> <span class="token number">0</span></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> nums <span class="token punctuation">{</span> <span class="token comment">// 使用 range 关键字获取索引 i</span></span>
<span class="line">		s <span class="token operator">+=</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> </span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">return</span> s</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>6 指针</h2>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token comment">// golang 中的指针不能运算</span></span>
<span class="line"><span class="token comment">// golang 中只有值传递</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> a <span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">2</span></span>
<span class="line">	<span class="token keyword">var</span> pa <span class="token operator">*</span><span class="token builtin">int</span> <span class="token operator">=</span> <span class="token operator">&amp;</span>a <span class="token comment">// 用一个 * 号代表 pa 是一个指向 int 数据类型的指针; pa 的值是 a 的地址</span></span>
<span class="line">	<span class="token operator">*</span>pa <span class="token operator">=</span> <span class="token number">3</span> <span class="token comment">// 在使用 pa 的时候加上 * 号代表的就是 pa 指向的那个数据本身了</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>pa<span class="token punctuation">,</span> <span class="token operator">*</span>pa<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">0x140000a6018 3</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>作为参数传递</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">modifyValue</span><span class="token punctuation">(</span>nums <span class="token operator">*</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token operator">*</span>nums <span class="token operator">=</span> <span class="token number">666</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// go 语言中只有值传递，我们可以把 nums 的地址传进去</span></span>
<span class="line"><span class="token comment">// 通过地址访问 nums 所代表的内存区域本身</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	nums <span class="token operator">:=</span> <span class="token number">111</span></span>
<span class="line">	<span class="token function">modifyValue</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>nums<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>nums<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">666</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2>7 内建容器：数组</h2>
<p><strong>数组</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> arr1 <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token comment">// 指定数组长度为 5； 每个元素的类型是 int 类型</span></span>
<span class="line">	arr2 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span> <span class="token comment">// 还可以赋初值</span></span>
<span class="line">	arr3 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">}</span> <span class="token comment">// 写 ... 代表这个数组的长度根据你填写的数值个数进行自动生成</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr1<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr2<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr3<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">var</span> grid <span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token comment">// 一个 4 行 5 列的二维数组</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>grid<span class="token punctuation">)</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// 使用 len 可以获取数组的长度</span></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token function">len</span><span class="token punctuation">(</span>arr3<span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr3<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"range 1"</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token comment">// 只返回数组的索引 i</span></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> arr3 <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr3<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"range 2"</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token comment">// 返回索引 i 的同时返回这个位置的值 v</span></span>
<span class="line">	<span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> arr3 <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>k<span class="token punctuation">,</span> v<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">[0 0 0 0 0]</span>
<span class="line">[1 2 3]</span>
<span class="line">[2 4 6 8 10]</span>
<span class="line">[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]</span>
<span class="line">2</span>
<span class="line">4</span>
<span class="line">6</span>
<span class="line">8</span>
<span class="line">10</span>
<span class="line">range 1</span>
<span class="line">2</span>
<span class="line">4</span>
<span class="line">6</span>
<span class="line">8</span>
<span class="line">10</span>
<span class="line">range 2</span>
<span class="line">0 2</span>
<span class="line">1 4</span>
<span class="line">2 6</span>
<span class="line">3 8</span>
<span class="line">4 10</span>
<span class="line"></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>数组数值类型</strong></p>
<p>数组名代表的是数组全部的内容，因此数组的长度不一样代表的是两种不同的数据类型，比如：</p>
<p><code>arr1 [5]int</code> 和 <code>arr2 [3]int</code> 是两种不同的数组 并且 从数组到数组的参数传递是基于拷贝的</p>
<h2>8 内建容器：切片</h2>
<p><strong>切片</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">}</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// 和 python 里面的切片很像</span></span>
<span class="line">    <span class="token comment">// go 中的切片是以一个具体的数组作为载体的</span></span>
<span class="line">    <span class="token comment">// 切片是对这个数组的一个 view，仅仅是一个引用</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"arr[2:6] = "</span><span class="token punctuation">,</span> arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"arr[:6] = "</span><span class="token punctuation">,</span> arr<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"arr[2:] = "</span><span class="token punctuation">,</span> arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"arr[:] = "</span><span class="token punctuation">,</span> arr<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">arr[2:6] =  [2 3 4 5]</span>
<span class="line">arr[:6] =  [0 1 2 3 4 5]</span>
<span class="line">arr[2:] =  [2 3 4 5 6 7 8]</span>
<span class="line">arr[:] =  [0 1 2 3 4 5 6 7 8]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>切片是 view</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">updateSplice</span><span class="token punctuation">(</span>s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> i<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> s <span class="token punctuation">{</span></span>
<span class="line">		s<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> v <span class="token operator">+</span> <span class="token number">1</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token function">updateSplice</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token function">updateSplice</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">[1 2 3 4 5 6 7 8 9]</span>
<span class="line">[2 3 4 5 6 7 8 9 10]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>切片的可扩展性</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	s1 <span class="token operator">:=</span> arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"s1: "</span><span class="token punctuation">,</span> s1<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s1) = %d, cap(s1) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	s2 <span class="token operator">:=</span> s1<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token comment">// 数组本身还在, slice 只是数组的 view</span></span>
<span class="line">    <span class="token comment">// 你可以发现，我们竟然能访问这个切片以后的内容；因为这些内容真实存在于底层数组中</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"s2: "</span><span class="token punctuation">,</span> s2<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s2) = %d, cap(s2) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// slice 的实现</span></span>
<span class="line">	<span class="token comment">// 1. ptr 指向 slice 开始的元素</span></span>
<span class="line">	<span class="token comment">// 2. len 代表 slice 的长度</span></span>
<span class="line">	<span class="token comment">// 3. cap 代表 ptr 到数组末尾的长度; 因此可向后扩展, 但是不能向前扩展</span></span>
<span class="line">	<span class="token comment">// slice[i] 其中 i &lt; len ; slice[s, e] 其中 e &lt;= cap 即可</span></span>
<span class="line">    <span class="token comment">// len 仅代表 slice 的长度，而 cap 代表的是这个切片的起始位置到这个底层的数组的结束位置的长度</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">s1:  [2 3 4 5]</span>
<span class="line">len(s1) = 4, cap(s1) = 6 </span>
<span class="line">s2:  [5 6]</span>
<span class="line">len(s2) = 2, cap(s2) = 3 </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>对切片添加元素</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	s1 <span class="token operator">:=</span> arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"s1: "</span><span class="token punctuation">,</span> s1<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s1) = %d, cap(s1) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	s2 <span class="token operator">:=</span> s1<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token comment">// 数组本身还在, slice 只是数组的 view</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"s2: "</span><span class="token punctuation">,</span> s2<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s2) = %d, cap(s2) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// slice 的实现</span></span>
<span class="line">	<span class="token comment">// 1. ptr 指向 slice 开始的元素</span></span>
<span class="line">	<span class="token comment">// 2. len 代表 slice 的长度</span></span>
<span class="line">	<span class="token comment">// 3. cap 代表 ptr 到数组末尾的长度; 因此可向后扩展, 但是不能向前扩展</span></span>
<span class="line">	<span class="token comment">// slice[i] 其中 i &lt; len ; slice[s, e] 其中 e &lt;= cap 即可</span></span>
<span class="line"></span>
<span class="line">	s3 <span class="token operator">:=</span> <span class="token function">append</span><span class="token punctuation">(</span>s2<span class="token punctuation">,</span> <span class="token number">111</span><span class="token punctuation">)</span></span>
<span class="line">	s4 <span class="token operator">:=</span> <span class="token function">append</span><span class="token punctuation">(</span>s3<span class="token punctuation">,</span> <span class="token number">222</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"v = %v, len(s3) = %d, cap(s3) = %d \n"</span><span class="token punctuation">,</span> s3<span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s3<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s3<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"v = %v, len(s4) = %d, cap(s4) = %d \n"</span><span class="token punctuation">,</span> s4<span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s4<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s4<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 添加元素的时候如果超过了底层数组的 cap, 则会重新分配一个底层数组</span></span>
<span class="line">    <span class="token comment">// 所以 append 每次都会返回一个新的引用，因为我们可以已经抛弃了原来的那个底层数组</span></span>
<span class="line">	<span class="token comment">// 因此在添加元素的时候随时都有可能造成底层数组的改变, 因此必须接收 append 的返回值</span></span>
<span class="line">	<span class="token comment">// 从而使用一个新的 切片 来对数组进行 view</span></span>
<span class="line">	s4<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">999</span> <span class="token comment">// 此时切片 s3 和 s4 已经不是同一个数组的 view 了, 是 go 重新帮我们分配的数组了</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"v = %v, len(s3) = %d, cap(s3) = %d \n"</span><span class="token punctuation">,</span> s3<span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s3<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s3<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"v = %v, len(s4) = %d, cap(s4) = %d \n"</span><span class="token punctuation">,</span> s4<span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s4<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s4<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>直接创建 切片</strong></p>
<p>直接创建切片的话，go 会自动为我们创建底层数组，因此，我们创建的切片看上去就好像是那个数组的引用一样</p>
<p>实际上切片中存储的是指向这个数组的指针，我们拷贝切片其实拷贝的是那个指针，因此我们操作这个切片的拷贝，实际上操作的是同一个底层数组</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token comment">// 直接定义 slice 类型, 此时 s 的值为 nil</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 观察 cap 的变化</span></span>
<span class="line">        <span class="token comment">// 当 cap 产生变化的时候，说明引用的底层数组已经变了</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s) = %d, cap(s) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">		s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> i<span class="token operator">*</span><span class="token number">2</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">0</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">1</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">2</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">4</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">4</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">8</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">8</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">8</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">8</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">11</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">12</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">13</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">14</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">15</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">16</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">17</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">19</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">21</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">22</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">23</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">24</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">25</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">26</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">27</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">28</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">29</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">30</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">31</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">32</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">33</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">34</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">35</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">36</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">37</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">38</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">39</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">40</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">41</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">43</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">44</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">45</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">46</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">47</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">48</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">49</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">50</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">51</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">52</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">53</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">54</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">55</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">56</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">57</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">58</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">59</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">60</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">61</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">62</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">63</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">64</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">65</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">66</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">67</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">68</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">69</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">70</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">71</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">72</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">73</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">74</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">75</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">76</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">77</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">78</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">79</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">80</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">81</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">82</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">83</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">84</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">85</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">86</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">87</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">88</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">89</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">90</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">91</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">92</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">93</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">94</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">95</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">97</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">98</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span> </span>
<span class="line"><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">99</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">128</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>按长度创建切片</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s) = %d, cap(s) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	ss <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">32</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(ss) = %d, cap(ss) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token function">copy</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> ss<span class="token punctuation">)</span>  <span class="token comment">// 只会根据 s 的容量 cap 进行拷贝, 超过容量大小的部分不拷贝</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s) = %d, cap(s) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">len(s) = 18, cap(s) = 18 </span>
<span class="line">len(ss) = 20, cap(ss) = 32 </span>
<span class="line">len(s) = 18, cap(s) = 18</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>切片删除元素</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">,</span> <span class="token number">32</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(s) = %d, cap(s) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 删除中间某个元素</span></span>
<span class="line">	ss <span class="token operator">:=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span> s<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"len(ss) = %d, cap(ss) = %d \n"</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">111</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 删除头元素</span></span>
<span class="line">	ss <span class="token operator">=</span> ss<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 删除尾元素</span></span>
<span class="line">	ss <span class="token operator">=</span> ss<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token function">len</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">len(s) = 16, cap(s) = 32 </span>
<span class="line">len(ss) = 15, cap(ss) = 32 </span>
<span class="line">[111 0 0 0 0 0 0 0 0 0 0 0 0 0 0]</span>
<span class="line">[0 0 0 0 0 0 0 0 0 0 0 0 0 0]</span>
<span class="line">[0 0 0 0 0 0 0 0 0 0 0 0 0]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>9 内建容器：map</h2>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token comment">// map 是无序的</span></span>
<span class="line">    <span class="token comment">// 除了 slice, map, function 的内建类型都可以作为 key</span></span>
<span class="line">    <span class="token comment">// 创建一个 k 和 v 都是 string 类型的 map</span></span>
<span class="line">	m <span class="token operator">:=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">{</span></span>
<span class="line">		<span class="token string">"name"</span><span class="token punctuation">:</span>    <span class="token string">"blueberry"</span><span class="token punctuation">,</span></span>
<span class="line">		<span class="token string">"address"</span><span class="token punctuation">:</span> <span class="token string">"China"</span><span class="token punctuation">,</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	m2 <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token comment">// empty map</span></span>
<span class="line">	<span class="token keyword">var</span> m3 <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">string</span>      <span class="token comment">// nil: 同样可以参与运算</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m2<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m3<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	height<span class="token punctuation">,</span> ok <span class="token operator">:=</span> m<span class="token punctuation">[</span><span class="token string">"height"</span><span class="token punctuation">]</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"height: "</span><span class="token punctuation">,</span> height<span class="token punctuation">)</span> <span class="token comment">// 拿到的是空串</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ok: "</span><span class="token punctuation">,</span> ok<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 一般情况下可以这样写,</span></span>
<span class="line">	<span class="token keyword">if</span> height2<span class="token punctuation">,</span> okk <span class="token operator">:=</span> m<span class="token punctuation">[</span><span class="token string">"height"</span><span class="token punctuation">]</span><span class="token punctuation">;</span> okk <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ok height: "</span><span class="token punctuation">,</span> height2<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> m <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>k<span class="token punctuation">,</span> v<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 删除元素</span></span>
<span class="line">	<span class="token function">delete</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> <span class="token string">"name"</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"delete name: "</span><span class="token punctuation">,</span> m<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 创建复合 map</span></span>
<span class="line">	mm <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>mm<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	mm<span class="token punctuation">[</span><span class="token string">"blueberry"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span></span>
<span class="line">	mm<span class="token punctuation">[</span><span class="token string">"blueberry"</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">"name"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"111"</span></span>
<span class="line">	mm<span class="token punctuation">[</span><span class="token string">"blueberry"</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string">"height"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"222"</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>mm<span class="token punctuation">[</span><span class="token string">"blueberry"</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">map[address:China name:blueberry]</span>
<span class="line">map[]</span>
<span class="line">map[]</span>
<span class="line">height:  </span>
<span class="line">ok:  false</span>
<span class="line">name blueberry</span>
<span class="line">address China</span>
<span class="line">delete name:  map[address:China]</span>
<span class="line">map[]</span>
<span class="line">map[height:222 name:111]</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>10 golang 的面向对象</h2>
<p>golang 仅支持封装，不支持继承和多态；可以面向接口编程</p>
<p><strong>结构体</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> main</span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> <span class="token punctuation">(</span></span>
<span class="line">	<span class="token string">"fmt"</span></span>
<span class="line"><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// type 代表 User 是一个数据类型</span></span>
<span class="line"><span class="token comment">// struct 代表 User 是一个 struct 类型的数据类型</span></span>
<span class="line"><span class="token comment">// 然后在花括号内定义具体的内容</span></span>
<span class="line"><span class="token keyword">type</span> User <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	name    <span class="token builtin">string</span></span>
<span class="line">	address <span class="token builtin">string</span></span>
<span class="line">	height  <span class="token builtin">int</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">createUser</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> address <span class="token builtin">string</span><span class="token punctuation">,</span> height <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">*</span>User <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> <span class="token operator">&amp;</span>User<span class="token punctuation">{</span>name<span class="token punctuation">:</span> name<span class="token punctuation">,</span> address<span class="token punctuation">:</span> address<span class="token punctuation">,</span> height<span class="token punctuation">:</span> height<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token comment">// 1. 直接创建</span></span>
<span class="line">	<span class="token keyword">var</span> user1 User</span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 2. 赋初值</span></span>
<span class="line">	user2 <span class="token operator">:=</span> User<span class="token punctuation">{</span></span>
<span class="line">		name<span class="token punctuation">:</span>    <span class="token string">"blueberry"</span><span class="token punctuation">,</span></span>
<span class="line">		address<span class="token punctuation">:</span> <span class="token string">"China"</span><span class="token punctuation">,</span></span>
<span class="line">		height<span class="token punctuation">:</span>  <span class="token number">999</span><span class="token punctuation">,</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 3. 创建 User 并返回它的指针</span></span>
<span class="line">	user3 <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>User<span class="token punctuation">)</span></span>
<span class="line">	user3<span class="token punctuation">.</span>height <span class="token operator">=</span> <span class="token number">111</span></span>
<span class="line">	user3<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"blueberry3"</span></span>
<span class="line">	user3<span class="token punctuation">.</span>address <span class="token operator">=</span> <span class="token string">"US"</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 4. 所谓构造函数</span></span>
<span class="line">	user4 <span class="token operator">:=</span> <span class="token function">createUser</span><span class="token punctuation">(</span><span class="token string">"blueberry"</span><span class="token punctuation">,</span> <span class="token string">"China and US"</span><span class="token punctuation">,</span> <span class="token number">999</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 看看内容</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>user1<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>user2<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>user2<span class="token punctuation">.</span>name<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>user3<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>user4<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">{  0}</span>
<span class="line">{blueberry China 999}</span>
<span class="line">blueberry</span>
<span class="line">&amp;{blueberry3 US 111}</span>
<span class="line">&amp;{blueberry China and US 999}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>为结构定义方法</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> main</span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> <span class="token punctuation">(</span></span>
<span class="line">	<span class="token string">"fmt"</span></span>
<span class="line"><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">type</span> User <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	name    <span class="token builtin">string</span></span>
<span class="line">	address <span class="token builtin">string</span></span>
<span class="line">	height  <span class="token builtin">int</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">createUser</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> address <span class="token builtin">string</span><span class="token punctuation">,</span> height <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">*</span>User <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> <span class="token operator">&amp;</span>User<span class="token punctuation">{</span>name<span class="token punctuation">:</span> name<span class="token punctuation">,</span> address<span class="token punctuation">:</span> address<span class="token punctuation">,</span> height<span class="token punctuation">:</span> height<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 使用指针接受者定义的方法</span></span>
<span class="line"><span class="token comment">// 当使用指针接收者的时候，不会每次在调用 print 的时候都把 User 的内容拷贝一次</span></span>
<span class="line"><span class="token comment">// 而是传递 User 实例的指针给 user 这个变量，这时候你可以通过 user 改变它的内容对外界产生影响</span></span>
<span class="line"><span class="token comment">// 当然，你可以把 * 号去掉，一旦去掉，就会拷贝 User 里面的内容给 user 变量，你所作出的改变对外界没有影响</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>user <span class="token operator">*</span>User<span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"name: "</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span>name<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"address: "</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span>address<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"height: "</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span>height<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	user <span class="token operator">:=</span> <span class="token function">createUser</span><span class="token punctuation">(</span><span class="token string">"blueberry"</span><span class="token punctuation">,</span> <span class="token string">"China and US"</span><span class="token punctuation">,</span> <span class="token number">999</span><span class="token punctuation">)</span></span>
<span class="line">	user<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">name:  blueberry</span>
<span class="line">address:  China and US</span>
<span class="line">height:  999 </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>11 go 的包</h2>
<p></p>
<p><strong>user.go</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> user</span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> <span class="token string">"fmt"</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 大写开头代表的是在其他包内也可以访问</span></span>
<span class="line"><span class="token comment">// 小写开头的话只能在当前的包内访问</span></span>
<span class="line"><span class="token comment">// type 指明 User 是一个数据结构</span></span>
<span class="line"><span class="token keyword">type</span> User <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	Name    <span class="token builtin">string</span></span>
<span class="line">	Address <span class="token builtin">string</span></span>
<span class="line">	Height  <span class="token builtin">int</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">CreateUser</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> address <span class="token builtin">string</span><span class="token punctuation">,</span> height <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">*</span>User <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> <span class="token operator">&amp;</span>User<span class="token punctuation">{</span>Name<span class="token punctuation">:</span> name<span class="token punctuation">,</span> Address<span class="token punctuation">:</span> address<span class="token punctuation">,</span> Height<span class="token punctuation">:</span> height<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>user <span class="token operator">*</span>User<span class="token punctuation">)</span> <span class="token function">Print</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"name: "</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span>Name<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"address: "</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span>Address<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"height: "</span><span class="token punctuation">,</span> user<span class="token punctuation">.</span>Height<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>main.go</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> main</span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> <span class="token punctuation">(</span></span>
<span class="line">	<span class="token string">"fmt"</span></span>
<span class="line">	<span class="token string">"learngo/user"</span></span>
<span class="line"><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	blueberry <span class="token operator">:=</span> user<span class="token punctuation">.</span><span class="token function">CreateUser</span><span class="token punctuation">(</span><span class="token string">"blueberry"</span><span class="token punctuation">,</span> <span class="token string">"China and US"</span><span class="token punctuation">,</span> <span class="token number">999</span><span class="token punctuation">)</span></span>
<span class="line">	blueberry<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>blueberry<span class="token punctuation">.</span>Name<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">name:  blueberry</span>
<span class="line">address:  China and US</span>
<span class="line">height:  999</span>
<span class="line">blueberry</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>type 关键字</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token comment">// 还可以使用 type 为 []int 起一个别名</span></span>
<span class="line"><span class="token keyword">type</span> Queue <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h2>12 接口 Interface</h2>
<p></p>
<p><strong>Retriever.go</strong></p>
<p>定义结构体</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> mock</span>
<span class="line"></span>
<span class="line"><span class="token keyword">type</span> Retriever <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	Contents <span class="token builtin">string</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Retriever<span class="token punctuation">)</span> <span class="token function">Get</span><span class="token punctuation">(</span>url <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> r<span class="token punctuation">.</span>Contents</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>main.go</strong></p>
<p>定义结构并使用接口接收 <code>Retriever</code> 结构体的实例；使用接口接收结构体的实例就可以完成不同的结构体之间使用同一个类型的变量进行引用了，就像 <code>Python</code> 中一样灵活，甚至使用一个接口类型的数组可以让每个元素引用多个不同类型的结构体实例，遍历这个数组并且调用同一个方法！</p>
<p>接口变量中包含两个内容：</p>
<ol>
<li>实现者的类型 <code>%T</code></li>
<li>实现者的拷贝 或者 指向实现者的指针 <code>%v</code></li>
</ol>
<p>使用接口的时候，为接口赋值分为两种情况：</p>
<ol>
<li>指针接收者：若结构体绑定的方法使用的是指针接收者，则为接口赋值的时候要取地址</li>
<li>值接收者：若结构体绑定的方法使用的是值接收者，则为接口赋值的时候可以取地址也可以不取地址，如果是以取地址的方式进行复制，那么接口变量中包含的就是指向结构体实例的指针，如果不取地址则接口变量中包含一份结构体实例的拷贝</li>
</ol>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> main</span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> <span class="token punctuation">(</span></span>
<span class="line">	<span class="token string">"fmt"</span></span>
<span class="line">	<span class="token string">"learngo/mock"</span></span>
<span class="line"><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">type</span> Retriever <span class="token keyword">interface</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token function">Get</span><span class="token punctuation">(</span>url <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">download</span><span class="token punctuation">(</span>r Retriever<span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> r<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">"www.baidu.com"</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> r Retriever</span>
<span class="line">	r <span class="token operator">=</span> <span class="token operator">&amp;</span>mock<span class="token punctuation">.</span>Retriever<span class="token punctuation">{</span>Contents<span class="token punctuation">:</span> <span class="token string">"hello world."</span><span class="token punctuation">}</span> <span class="token comment">// 指针接收者</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">download</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">hello world.</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>一般类型</strong></p>
<p><code>interface {}</code> 代表的是任意类型，当 <code>interface</code> 中不写任何方法的时候则代表不用实现任何方法的类型都可以被该接口接收，所以就是代表任意类型咯； 在某些情况下这样做产生的代价就是可能只有在运行的时候才能知道会报错</p>
<p><strong>接口组合</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">type</span> Retriever <span class="token keyword">interface</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token function">Get</span><span class="token punctuation">(</span>url <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">type</span> Poster <span class="token keyword">interface</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token function">Post</span><span class="token punctuation">(</span>url <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 组合后：RetrieverPoster 可以调用 Get 和 Post</span></span>
<span class="line"><span class="token keyword">type</span> RetrieverPoster <span class="token keyword">interface</span> <span class="token punctuation">{</span></span>
<span class="line">	Retriever</span>
<span class="line">	Poster</span>
<span class="line">	<span class="token function">Connect</span><span class="token punctuation">(</span>host <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>Reader Writer 接口</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token comment">// 使用 io.Reader 接口的例子</span></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">printFileContents</span><span class="token punctuation">(</span>reader io<span class="token punctuation">.</span>Reader<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	scanner <span class="token operator">:=</span> bufio<span class="token punctuation">.</span><span class="token function">NewScanner</span><span class="token punctuation">(</span>reader<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> scanner<span class="token punctuation">.</span><span class="token function">Scan</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>scanner<span class="token punctuation">.</span><span class="token function">Text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	file<span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"hello.txt"</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">if</span> err <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token function">printFileContents</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	ss <span class="token operator">:=</span> <span class="token string">"I \nam \nblueberry \ngo on"</span></span>
<span class="line"></span>
<span class="line">	<span class="token function">printFileContents</span><span class="token punctuation">(</span>strings<span class="token punctuation">.</span><span class="token function">NewReader</span><span class="token punctuation">(</span>ss<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line">hello</span>
<span class="line">world</span>
<span class="line"><span class="token number">1</span></span>
<span class="line"><span class="token number">2</span></span>
<span class="line"><span class="token number">3</span></span>
<span class="line"><span class="token number">4</span></span>
<span class="line"><span class="token number">5</span></span>
<span class="line">I </span>
<span class="line">am </span>
<span class="line">blueberry </span>
<span class="line"><span class="token keyword">go</span> on</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>stringer 接口</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token comment">// 实现 stringer 接口 ==> 用于格式化为字符串</span></span>
<span class="line"><span class="token keyword">type</span> User <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	name <span class="token builtin">string</span></span>
<span class="line">	age  <span class="token builtin">int</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>u User<span class="token punctuation">)</span> <span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"name is %s, age is %d"</span><span class="token punctuation">,</span> u<span class="token punctuation">.</span>name<span class="token punctuation">,</span> u<span class="token punctuation">.</span>age<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> user User</span>
<span class="line">	user<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"blueberry"</span></span>
<span class="line">	user<span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">999</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"the user contents: %s\n"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"the user contents:"</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">the user contents:name is blueberry, age is 999</span>
<span class="line">the user contents: name is blueberry, age is 999</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>type</strong></p>
<p>到这里可以搜索一下类型断言 <code>type assertion</code> 和 <code>type switch</code> 相关的内容，这里就不展开写了</p>
<h2>13 Goroutine 并发编程</h2>
<p><strong>go 关键字：创建 goroutine</strong></p>
<ol>
<li>
<p>goroutine 是轻量级的线程，类似于协程</p>
</li>
<li>
<p>非抢占式多任务处理，由协程主动交出控制权：碰到 io 操作的时候会主动交出控制权</p>
</li>
</ol>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 在调用函数的时候使用 go 关键字，就相当于让该函数相对于调用它的那个执行流而言并发了</span></span>
<span class="line">		<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>num <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">			<span class="token keyword">for</span> <span class="token punctuation">{</span></span>
<span class="line">				fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Hello World from goroutine:"</span><span class="token punctuation">,</span> num<span class="token punctuation">)</span> <span class="token comment">// 碰到这行 io 操作会主动拐交出控制权</span></span>
<span class="line">				runtime<span class="token punctuation">.</span><span class="token function">Gosched</span><span class="token punctuation">(</span><span class="token punctuation">)</span>                               <span class="token comment">// 主动交出控制权</span></span>
<span class="line">			<span class="token punctuation">}</span></span>
<span class="line">		<span class="token punctuation">}</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Millisecond<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">Hello World from goroutine: 2</span>
<span class="line">Hello World from goroutine: 4</span>
<span class="line">Hello World from goroutine: 4</span>
<span class="line">Hello World from goroutine: 1</span>
<span class="line">Hello World from goroutine: 1</span>
<span class="line">Hello World from goroutine: 1</span>
<span class="line">Hello World from goroutine: 7</span>
<span class="line">Hello World from goroutine: 7</span>
<span class="line">Hello World from goroutine: 2</span>
<span class="line">Hello World from goroutine: 2</span>
<span class="line">Hello World from goroutine: 2</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 0</span>
<span class="line">Hello World from goroutine: 8</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>go 语言调度器</strong></p>
<p>go 语言会根据需要开一定数量的线程；goroutine 是放在线程中运行的，至于放在哪个线程中被操作系统调度进而运行要看 go 语言自己进行调度；调度器会在合适的位置进行自动切换</p>
<ol>
<li>I/O 或者 select</li>
<li>channel</li>
<li>等待锁的时候</li>
<li>有时在函数调用的时候进行切换</li>
<li>runtime.Gosched()</li>
</ol>
<p>某些其他的地方也可能会切换；本质还是非抢占式的</p>
<h2>14 Channel 通道</h2>
<p>协程之间通信的机制 Channel</p>
<p><strong>创建 channel</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">package</span> main</span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> <span class="token punctuation">(</span></span>
<span class="line">	<span class="token string">"fmt"</span></span>
<span class="line">	<span class="token string">"time"</span></span>
<span class="line"><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>ch <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> <span class="token punctuation">{</span></span>
<span class="line">		n <span class="token operator">:=</span> <span class="token operator">&lt;-</span>ch</span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> c <span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token comment">// 此时的 c 是 nil</span></span>
<span class="line">	<span class="token comment">//c = make(chan int) 通过这种方式创建的 channel 是没有缓存的; 发送后若接收方没有收完，发送方会阻塞</span></span>
<span class="line">	c <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token comment">// 需要 make 出来; 创建一个能够缓存 10 个 int 类型数据的 channel</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">go</span> <span class="token function">worker</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">		c <span class="token operator">&lt;-</span> i</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line">    <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token comment">// 当关闭 channel 后，接收方还是可以收数据的，收到的是具体类型的零值</span></span>
<span class="line"></span>
<span class="line">	time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Millisecond <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">0</span>
<span class="line">1</span>
<span class="line">2</span>
<span class="line">3</span>
<span class="line">4</span>
<span class="line">5</span>
<span class="line">6</span>
<span class="line">7</span>
<span class="line">8</span>
<span class="line">9</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>接收方判断 channel 是否关闭</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>ch <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 我们可以在接受数据的时候这样做</span></span>
<span class="line">        <span class="token comment">// ok 中是一个布尔值</span></span>
<span class="line">		n<span class="token punctuation">,</span> ok <span class="token operator">:=</span> <span class="token operator">&lt;-</span>ch</span>
<span class="line">		<span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span></span>
<span class="line">			<span class="token keyword">break</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>使用 range</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>ch <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> n <span class="token operator">:=</span> <span class="token keyword">range</span> ch <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// 使用这样的方法遍历，如果 channel 不被 close</span></span>
<span class="line">        <span class="token comment">// 那么当 channel 空了之后会一直等待</span></span>
<span class="line">        <span class="token comment">// 直到程序运行结束</span></span>
<span class="line">        <span class="token comment">// 如果 channel 被 close 了，那么该过程也就结束了</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>等待 goroutine 完成的方法</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>ch <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> done <span class="token keyword">chan</span> <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> n <span class="token operator">:=</span> <span class="token keyword">range</span> ch <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line">	done <span class="token operator">&lt;-</span> <span class="token boolean">true</span> <span class="token comment">// 如果这里不往通道内输入一个值，那么 generator 那里就要一直等待下去了</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span></span>
<span class="line">	done <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">bool</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">go</span> <span class="token function">worker</span><span class="token punctuation">(</span>c<span class="token punctuation">,</span> done<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">		c <span class="token operator">&lt;-</span> i</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span></span>
<span class="line">	<span class="token operator">&lt;-</span>done <span class="token comment">// 用好 channel 阻塞的特性，使用一个 channel 进行等待</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>使用 WaitGroup</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>ch <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> wg <span class="token operator">*</span>sync<span class="token punctuation">.</span>WaitGroup<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> n <span class="token operator">:=</span> <span class="token keyword">range</span> ch <span class="token punctuation">{</span></span>
<span class="line">		fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line">	wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup</span>
<span class="line">	wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// 代表执行 1 次 Done 之后就算完成等待了</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">go</span> <span class="token function">worker</span><span class="token punctuation">(</span>c<span class="token punctuation">,</span> <span class="token operator">&amp;</span>wg<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">		c <span class="token operator">&lt;-</span> i</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">	<span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span></span>
<span class="line">	wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 直到使用 wg 执行 1 次 Done 操作后，这里才会通过</span></span>
<span class="line">    <span class="token comment">// 具体是 wg 执行几次 Done 操作才会通过这要看在使用 wg.Add 的时候那个值添加的是几</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>select 调度</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">generator</span><span class="token punctuation">(</span>c <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">1000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">		c <span class="token operator">&lt;-</span> i</span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> c1 <span class="token keyword">chan</span> <span class="token builtin">int</span></span>
<span class="line">	<span class="token keyword">var</span> c2 <span class="token keyword">chan</span> <span class="token builtin">int</span></span>
<span class="line">	c1 <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span></span>
<span class="line">	c2 <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">go</span> <span class="token function">generator</span><span class="token punctuation">(</span>c1<span class="token punctuation">)</span></span>
<span class="line">	<span class="token keyword">go</span> <span class="token function">generator</span><span class="token punctuation">(</span>c2<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 当达到 5 秒后会自动向 tm 中发送一个数据</span></span>
<span class="line">	tm <span class="token operator">:=</span> time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span><span class="token number">5</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span></span>
<span class="line">	</span>
<span class="line">    <span class="token comment">// 写个死循环不停的使用 select </span></span>
<span class="line">	<span class="token keyword">for</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token comment">// select 会选择一个不会阻塞的 case 执行</span></span>
<span class="line">        <span class="token comment">// 如果都阻塞的话，那就等着就行了，或者是如果都阻塞但是有 default 那么就会执行 default 里面的内容</span></span>
<span class="line">		<span class="token comment">// Note: 若对一个值为 nil 的通道进行操作，则一定阻塞</span></span>
<span class="line">		<span class="token keyword">select</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token keyword">case</span> n <span class="token operator">:=</span> <span class="token operator">&lt;-</span>c1<span class="token punctuation">:</span> <span class="token comment">// c1 产生数据的时候走这里</span></span>
<span class="line">			fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"reveived from c1:"</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span></span>
<span class="line">		<span class="token keyword">case</span> n <span class="token operator">:=</span> <span class="token operator">&lt;-</span>c2<span class="token punctuation">:</span> <span class="token comment">// c2 产生数据的时候走这里</span></span>
<span class="line">			fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"reveived from c2:"</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span></span>
<span class="line">		<span class="token keyword">case</span> <span class="token operator">&lt;-</span>tm<span class="token punctuation">:</span> <span class="token comment">// 当达到 5 秒的时候，这里可以收数据</span></span>
<span class="line">			fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"done!"</span><span class="token punctuation">)</span></span>
<span class="line">			<span class="token keyword">return</span></span>
<span class="line">		<span class="token keyword">default</span><span class="token punctuation">:</span> <span class="token comment">// 当都无法收或发数据的时候走这个分支</span></span>
<span class="line">			fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"wait"</span><span class="token punctuation">)</span></span>
<span class="line">			time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Millisecond <span class="token operator">*</span> <span class="token number">100</span><span class="token punctuation">)</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">	<span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>outputs:</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">// 省略 ...</span>
<span class="line">reveived from c2: 65</span>
<span class="line">reveived from c1: 64</span>
<span class="line">wait</span>
<span class="line">reveived from c1: 65</span>
<span class="line">reveived from c2: 66</span>
<span class="line">wait</span>
<span class="line">reveived from c2: 67</span>
<span class="line">reveived from c1: 66</span>
<span class="line">wait</span>
<span class="line">reveived from c2: 68</span>
<span class="line">reveived from c1: 67</span>
<span class="line">wait</span>
<span class="line">reveived from c1: 68</span>
<span class="line">done!</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>传统的同步机制</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">type</span> atomicInt <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	value <span class="token builtin">int</span></span>
<span class="line">	lock  sync<span class="token punctuation">.</span>Mutex <span class="token comment">// 这是一把锁</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>atomicInt<span class="token punctuation">)</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token comment">// TODO: before lock</span></span>
<span class="line">	<span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token comment">// 使用匿名函数在一块儿代码区里锁定资源</span></span>
<span class="line">		a<span class="token punctuation">.</span>lock<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">		<span class="token keyword">defer</span> a<span class="token punctuation">.</span>lock<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">		a<span class="token punctuation">.</span>value<span class="token operator">++</span></span>
<span class="line">	<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token comment">//TODO: after unlock</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>atomicInt<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span></span>
<span class="line">	a<span class="token punctuation">.</span>lock<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 上锁</span></span>
<span class="line">	<span class="token keyword">defer</span> a<span class="token punctuation">.</span>lock<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 解锁</span></span>
<span class="line">    <span class="token comment">// 使用 defer 关键字就是代表在函数 return 之前才执行 defer 后面的语句</span></span>
<span class="line"></span>
<span class="line">	<span class="token keyword">return</span> a<span class="token punctuation">.</span>value</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token keyword">var</span> nums atomicInt</span>
<span class="line">	<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">		<span class="token keyword">for</span> <span class="token punctuation">{</span></span>
<span class="line">			nums<span class="token punctuation">.</span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">	<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Millisecond<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>nums<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title></title>
      <link>https://blueberry-universe.cn/2024-05-21-00/</link>
      <guid>https://blueberry-universe.cn/2024-05-21-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml"></source>
      <description>Golang 线程同步
通常在 Go 语言中有两种方法可以用来做线程同步

sync.Cond
channel

channel 的很好理解，当我们从一个 channel 中接收数据的时候，如果里面没有数据，那我们直接就阻塞在那里了；在这篇文章中就来看看怎么使用 sync.Cond 完成同步
sync.Cond
定义结构体和方法

主要逻辑
我们分别做...</description>
      <content:encoded><![CDATA[<h2>Golang 线程同步</h2>
<p>通常在 Go 语言中有两种方法可以用来做线程同步</p>
<ol>
<li>sync.Cond</li>
<li>channel</li>
</ol>
<p>channel 的很好理解，当我们从一个 channel 中接收数据的时候，如果里面没有数据，那我们直接就阻塞在那里了；在这篇文章中就来看看怎么使用 sync.Cond 完成同步</p>
<h2>sync.Cond</h2>
<p><strong>定义结构体和方法</strong></p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">type</span> BlueberryInt <span class="token keyword">struct</span> <span class="token punctuation">{</span></span>
<span class="line">	num  <span class="token builtin">int</span></span>
<span class="line">	lock sync<span class="token punctuation">.</span>Mutex</span>
<span class="line">	cond <span class="token operator">*</span>sync<span class="token punctuation">.</span>Cond</span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token function">NewBlueberryInt</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span>BlueberryInt <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 创建 BlueberryInt 结构体</span></span>
<span class="line">	<span class="token keyword">var</span> obj BlueberryInt</span>
<span class="line">	obj<span class="token punctuation">.</span>num <span class="token operator">=</span> <span class="token number">0</span></span>
<span class="line">	obj<span class="token punctuation">.</span>cond <span class="token operator">=</span> sync<span class="token punctuation">.</span><span class="token function">NewCond</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>obj<span class="token punctuation">.</span>lock<span class="token punctuation">)</span> <span class="token comment">// 使用结构体中的 lock 作为锁</span></span>
<span class="line">	<span class="token keyword">return</span> <span class="token operator">&amp;</span>obj <span class="token comment">// 返回该结构体的指针</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token function">IncreaseLocked</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// IncreaseLocked 意味着在做加法操作的时候这个函数需要上锁后才能使用</span></span>
<span class="line">	b<span class="token punctuation">.</span>num<span class="token operator">++</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token function">DecreaseLocked</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// IncreaseLocked 意味着在做减法操作的时候这个函数需要上锁后才能使用</span></span>
<span class="line">	b<span class="token punctuation">.</span>num<span class="token operator">--</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token function">Signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 当完成一件事情后，我们就发送 Signal</span></span>
<span class="line">	b<span class="token punctuation">.</span>cond<span class="token punctuation">.</span><span class="token function">Signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 当我们调用 Wait 的时候，我们还不能马上执行操作</span></span>
<span class="line">    <span class="token comment">// 我们需要收到 Signal 后 才可以继续执行</span></span>
<span class="line">	b<span class="token punctuation">.</span>cond<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 上锁</span></span>
<span class="line">	b<span class="token punctuation">.</span>lock<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token function">UnLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// 解锁</span></span>
<span class="line">	b<span class="token punctuation">.</span>lock<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>主要逻辑</strong></p>
<p>我们分别做 1000 次加法和 1000 次减法，但是呢，我们先让做减法的 goroutine 运行起来，并且使用 <code>Sleep</code> 等待 1 秒钟，确保它已经跑起来了；如果我们没有使用 <code>sync.Cond</code> 的话，这时候减法操作拿到锁之后就可以直接完成 1000 次的减法了，但是我们调用了 <code>num.Wait()</code> 来等待信号</p>
<p>为什么我们在做减法的 goroutine 中已经使用了 <code>num.Lock</code> 之后，在做加法的 goroutine 中还能够获得锁呢？这就是因为我们在 <code>NewBlueberryInt</code> 中的这行代码 <code>obj.cond = sync.NewCond(&amp;obj.lock)</code> ，但我们调用 <code>Wait</code> 的时候，它会先释放我们传入的那把锁并且阻塞在那里，然后等待信号的到来，当它收到信号之后重新获取那把锁然后再继续执行操作</p>
<div class="language-go line-numbers-mode" data-highlighter="prismjs" data-ext="go"><pre><code class="language-go"><span class="line"><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">	<span class="token comment">// 做了加法才能做减法</span></span>
<span class="line">	b <span class="token operator">:=</span> <span class="token function">NewBlueberryInt</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"the num b is %d \n"</span><span class="token punctuation">,</span> b<span class="token punctuation">.</span>num<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 做减法 1000 次</span></span>
<span class="line">	<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>num <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">		num<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">		num<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 等待信号</span></span>
<span class="line">		<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">1000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">			num<span class="token punctuation">.</span><span class="token function">DecreaseLocked</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">		num<span class="token punctuation">.</span><span class="token function">UnLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">	<span class="token punctuation">}</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	<span class="token comment">// 做加法 1000 次</span></span>
<span class="line">	<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>num <span class="token operator">*</span>BlueberryInt<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">		num<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">		<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">1000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span></span>
<span class="line">			num<span class="token punctuation">.</span><span class="token function">IncreaseLocked</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">		<span class="token punctuation">}</span></span>
<span class="line">		num<span class="token punctuation">.</span><span class="token function">Signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 发送信号</span></span>
<span class="line">		num<span class="token punctuation">.</span><span class="token function">UnLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 一定要记得释放锁，不然做减法的 goroutine 那里就永远走不动了</span></span>
<span class="line">	<span class="token punctuation">}</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span></span>
<span class="line"></span>
<span class="line">	b<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"the num b is %d \n"</span><span class="token punctuation">,</span> b<span class="token punctuation">.</span>num<span class="token punctuation">)</span></span>
<span class="line">	b<span class="token punctuation">.</span><span class="token function">UnLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后的输出结果就是这样的：</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">the num b is 0 </span>
<span class="line">the num b is 0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div>

]]></content:encoded>
    </item>
    <item>
      <title>思考的维度和付费意识</title>
      <link>https://blueberry-universe.cn/2022-04-29-00/</link>
      <guid>https://blueberry-universe.cn/2022-04-29-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">思考的维度和付费意识</source>
      <description>思考的维度和付费意识
这篇文章分享两部分内容

思考的维度
付费意识
分享一篇文章

在前几天我偶然间听了刘润老师的直播，觉得很有趣，我还做了一个笔记，分享一下。
1 思考的维度
0 维思考
从几何的角度来看，0 维是一个点。相信你一定听说过一句话：“掌握一项技能”。比如餐厅的厨师，他们的技术就是烹饪料理，再比如为视频或者文章写文案的小伙伴，他们的技能...</description>
      <content:encoded><![CDATA[
<p>这篇文章分享两部分内容</p>
<ol>
<li>思考的维度</li>
<li>付费意识</li>
<li>分享一篇文章</li>
</ol>
<p>在前几天我偶然间听了刘润老师的直播，觉得很有趣，我还做了一个笔记，分享一下。</p>
<h2>1 思考的维度</h2>
<p><strong>0 维思考</strong></p>
<p>从几何的角度来看，0 维是一个点。相信你一定听说过一句话：“掌握一项技能”。比如餐厅的厨师，他们的技术就是烹饪料理，再比如为视频或者文章写文案的小伙伴，他们的技能就是写文案。这都是属于一个点上的能力。0 维思考者是抱着自己的思想不懂得进化的人，就是一直停留在一个点上，想要用一个技术打遍天下。不能动，兵来将挡，水来土掩，就是不会动，一直是自己那一套技能</p>
<p>总结：0 维思考 就是 战术 就是 手艺。</p>
<p><strong>1 维思考</strong></p>
<p>1 维思考属于战略层面，在 1 维就是一根直线，有了前和后，前进或者后退。</p>
<p>有了梦想就有了目标，就是 1 维了，我们开始选定一个方向，并且去朝着方向出发。比如要登上一座山，有很多条路可以选择。假设其中一条路是在上午偏向中午的时间有很多很多的人开始登上这条路并且比较好走的一条路，还有另外一条路就是几乎没有什么人去但是登山的过程很复杂，因为路不好走。</p>
<ol>
<li>如果我们选择第一条路，正面上山就要早起，千军人马，需要勤奋的能力。</li>
<li>如果我们选择第二条路，那么我们就可以多睡一会，北面上山没人，但是要有更强的登山能力。</li>
</ol>
<p>总结：这两个方式都可以让我们登山，但是不同的选择需要不能的能力，没有最好战略，只有最适合自己的战略。</p>
<p>分享一下在刘润老师的直播里讲到了一个品牌：North Face</p>
<p>North Face 是 北面的意思，这是一个户外运动的品牌，North Face 的名字源于山上最冷最难攀登的北坡。</p>
<p><strong>2 维思考</strong></p>
<p>2 维思考是模式并且有了左右，什么模式呢，在商业中就是指 <strong>商业模式</strong></p>
<p>北大的魏伟教授定义商业模式 : 利益相关者的交易结构</p>
<p>如何理解呢？那就是：所在行业的玩家 供应商 广告商 巴啦吧啦，他们之间的利益关系交易结构。</p>
<p>举个例子：</p>
<p>在 2 维就像是开车，坐在主驾驶的人负责执行向前还是向后，主驾驶是 CEO 是首席执行官。但是坐在副驾驶的人就更重要了，副驾驶的人手中有一个城市的二维地图，从一个地方到另外一个地方，一条路走不通还可以选择另外一条。副驾驶才是那个知道全局的人，拿着地图的人是“上帝”。去空中看一看，上帝之眼，全局观。</p>
<p>总结：主驾驶是 CEO 负责执行，副驾驶是全局的指挥者，选错了路，奥迪不如奥拓。</p>
<p>在这里我用计算机的知识阐述一下我对选路的理解，在计算机中经常会要求最优解，但是很多问题似乎是没有最优解的，那么这时候，我们可以求一个局部最优解，一般来说也是一个不错的选择。</p>
<p><strong>3 维思考</strong></p>
<p>3 维在几何上来看是一个 <strong>体</strong>，3 维的思考是创新。</p>
<p>再次用驾车的例子：</p>
<p>堵车怎么办？如果你是城市的建设者，你是不是能够通过一些措施来优化这个情况呢？建个立交桥？可以从天上开过去？挖个隧道？可以从地底下开过去？</p>
<p>回到商业的世界：</p>
<p>跨境电商，相当于立交桥，中间商赚差价被跨越了，使得中国和某些国家直接建立了关系。有人说，这打击了实体店？那为什么实体店不能创新呢？</p>
<p>总结：3 维的思考是创新。</p>
<p>其实你有没有发现，我们生活在三维空间中，但是我们更像是生活在二维的世界中。</p>
<p>比如现在的疫情让我们隔离在小区里，简简单单的一个围墙一个栅栏一个门就把我们给挡住了？可是我们生活在三维世界里呀，我们不能从上边跨越吗？如果我们可以自由的在第三个维度上移动，那么现在的一切围墙对我们来说都不再是障碍了。古代的皇宫是围墙，美国的白宫也有围墙。如果有可穿戴的飞行设备，我们就可以在第三个维度自由移动。</p>
<p><strong>4 维思考</strong></p>
<p>4 维的思考是古今，是过去和未来，是在不同的历史时期，面对一件事情做出的决策。</p>
<p>总结：4 维加上了时间的概念，过去和未来。</p>
<p><strong>5 维思考</strong></p>
<p>5 维的思考是 <strong>概率</strong></p>
<p>这是这几个维度中，我最喜欢的。</p>
<p>为什么说是概率呢？比如我去打篮球，我每一次的投球都是有投中的概率和投不中的概率的。如果我可以有足够的力量控制能力，和非常正确的投球姿势，这能够很大程度上提高我投中的概率，但是我仍然是有投不中的概率。</p>
<p>说点玄幻的，这个世界可能是存在平行宇宙的，当我投中的那一瞬间，这个宇宙就分叉了，其中两个分叉的宇宙就是，我投中了和我没有投中，进而一直分叉下去，如果我属于那个一直投中的宇宙里边的我，那么我现在就是一个篮球巨星了，显然：我不属于那个我一直投中球的宇宙。哈！如果是的话，我现在就不会坐在这里敲键盘了。</p>
<p>接着刚才的说，什么是正确的投球姿势呢？正确的事情就是大概率成功的事情，正确的姿势没有投中的球都比错误的姿势投中要重要。因为存错的姿势让一个人投中，这只是 <strong>幸存者偏差</strong>。人人都知道，吸烟喝酒有害健康，为什么还有人说：你看！谁谁谁抽烟喝酒现在也长命百岁的，但是，我瞧瞧告诉你，可能 100 个有不良嗜好的人 99 个人都不太好了，只有一个幸存者让你看到了，因为只有活着的人才能说话，才能让你看到。</p>
<p>总结：正确的事情就是大概率成功的事情，正确的事情重复做，这能让我们大概率的成功，但不是绝对能成功。</p>
<p>这个世界不存在绝对能够成功的方法，这边这两句话，我以前非常的讨厌，现在，我对它们的想法变了。</p>
<ol>
<li>谋事在人，成事在天 Man disposes God disposes</li>
<li>尽人事，听天命</li>
</ol>
<p>Man disposes God disposes:</p>
<p>尽我们的所能，剩下的交给上帝交给运气来裁定。</p>
<p>最后分享一段话：</p>
<p>我们总是喜欢拿“顺其自然”来敷衍人生路上的荆棘坎坷，却很少承认，真正的顺其自然，其实是竭尽所能之后的不强求，而非两手一摊的不作为。</p>
<p>Instead of admitting that the truth of &quot;let it be&quot; is to readily accept any kind of outcome after making full efforts rather than to do nothing at the very beginning,we'd rather take &quot;let it be&quot; as an excuse to evade the path of thorns in our life.</p>
<h2>2 付费意识</h2>
<p>刚才我在浏览知识星球的时候，看到我关注的一个博主的球友问他，你现在做的社群都这么大了，而且知识星球这个平台扣除的付费手续费还不少，在 IOS 系统上扣除的更多，你为什么就没有想着自己去做一个软件来用呢？</p>
<p>博主：做一个软件，不仅需要开发的成本，还需要后期维护的成本，而且做一个社群本身就已经很不容易了。</p>
<p>总结：专业的事情交给专业的人来做，付费就是在买时间</p>
<p>如果你想使用盗版，可能为了省一点钱，你要花费一个上午来寻找盗版资源，可是你最后还可能找不到，而且你使用到的工具一定不仅只有这一个，在长期来看，这会浪费巨大的经历，让自己的主业甚至完成的很糟糕。最后得不偿失。</p>
<h2>分享一篇文章</h2>
<p>刘润：你们不懂罗永浩</p>


]]></content:encoded>
    </item>
    <item>
      <title></title>
      <link>https://blueberry-universe.cn/2023-07-05-00/</link>
      <guid>https://blueberry-universe.cn/2023-07-05-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml"></source>
      <description>不确定性才是常态；我希望你无限可能
今天我在朋友圈发了一条消息；我的一个朋友看到了这条消息后，就突然来找到聊天，我觉得这段聊天内容很有趣，分享给大家。
1、 我的朋友圈内容
IMG_5055
里面三张图的内容分别是：
IMG_5056
IMG_5057
IMG_5058
2、聊天内容

小伙伴：在某种程度上，他还是很让人佩服的，只是他看不起大多数人。人...</description>
      <content:encoded><![CDATA[<h2>不确定性才是常态；我希望你无限可能</h2>
<p>今天我在朋友圈发了一条消息；我的一个朋友看到了这条消息后，就突然来找到聊天，我觉得这段聊天内容很有趣，分享给大家。</p>
<p><strong>1、 我的朋友圈内容</strong></p>
<p></p>
<p>里面三张图的内容分别是：</p>
<p></p>
<p></p>
<p></p>
<p><strong>2、聊天内容</strong></p>
<blockquote>
<p>小伙伴：在某种程度上，他还是很让人佩服的，只是他看不起大多数人。人都是这样，看来他也是凡人，欲望满身。</p>
</blockquote>
<p>蓝莓：或许做个普通人 ~  然后才能放开枷锁，又不曾说过自己道德高尚，不曾说过自己是个圣人 ~ 没什么不好的，哈哈哈，而且，本来也就是个普通人。</p>
<blockquote>
<p>小伙伴：对 ~ 他和秦始皇死前在寻找长生不老药是一种目的。只是借助了高新科技 更科学了。</p>
</blockquote>
<p>蓝莓：我不清楚他是不是想一直活着。我记得乔布斯说过没有哪个人想要死去 ~ 不过我记得他说他想在生命结束前做什么事儿来着，是不是真的我也就不清楚了。不过从现在来看，人确实最终还是不能一直活着，那就尽可能尝试你想做的一切 ：）</p>
<blockquote>
<p>小伙伴：脑机接口应该是可行，也给自己留好了退路</p>
</blockquote>
<p>蓝莓：那就拭目以待叭 ~</p>
<blockquote>
<p>小伙伴：如果不成就葬在火星，真苦啊</p>
</blockquote>
<p>蓝莓：真不错 ~ 那就争取每个人都去追求 “酷”</p>
<blockquote>
<p>小伙伴：你有没有觉得 科学技术 和艺术 魔术 的术字是一种解释；其实就像变戏法～ 作品还是人的信仰。有了戏剧性 就很酷；抖音作品也是 不管搞笑的还是技术的 就是反差感</p>
</blockquote>
<p>蓝莓：这不太清楚了，我语文能力不怎么样，不过参考一下三体里面的想法，火鸡科学家 ~ 其实我觉得关于抖音作品这一点更应该去研究自媒体运营相关的内容。或许：自己的顿悟，只是别人的基本功。（或许这只是专业自媒体运营人的基本功）</p>
<p><strong>番外</strong>  什么是火鸡科学家呢？这是一个农场主的故事，有一家农场，这个农场里面有一群火鸡，这些火鸡被关在一个密闭的看不到外面世界的棚子里面。每天按时按点，农场主都会去给这些火鸡喂食。然后有一个“聪明”的火鸡就发现了，嗷！原来每天的一个特定时间都会有食物从天而降，因此这个“聪明”的火鸡就宣布我发现了世界运转的规律，因此这个火鸡也就是火鸡科学家。事实上很多东西都只是我们发现的规律，例如万有引力（有质量的物体会彼此吸引，因此我们和地球会彼此吸引）。有一天！他们到了这个时间点怎么等也等不来食物，结果这些火鸡都被 kill 掉了。</p>
<blockquote>
<p>小伙伴：做个不被定义的人吧 ~ 毕竟人生这么短，我也不是马斯克</p>
</blockquote>
<p>蓝莓：马斯克已经在那里了，没有人说过只有马斯克才能发射火箭，只不过恰好他发射了，你或许能发射飞船 ：）</p>
<blockquote>
<p>小伙伴：哈哈哈哈哈哈哈我只是callback人生很短 不像马斯克可以试图长生不老   [玫瑰][玫瑰]</p>
</blockquote>
<p>蓝莓：世界也不是线性发展的，人总是习惯性的用线性的方式推演未来，你未来或许无限可能 ~ 你或许能长生不老 ~ 哈哈哈 ~ 未来总是充满了不确定性 ~</p>
<blockquote>
<p>小伙伴：3q[玫瑰][玫瑰]</p>
</blockquote>
<p>蓝莓：哈哈哈，行 ~ 那快去做好准备，迎接不确定性 ~</p>
<p>=====================</p>
<p>不是鼓励大家反人性，而只是，不必道德绑架自己（又不是圣人，只是普通人）</p>
<p>希望你的未来无限可能，如果......如果说......你真的有你想去做的事情，那就屏蔽掉一些声音，专心去做叭。如果说，你还没有，或者还在寻找，又或者想法还没那么清晰。那就去慢慢寻找，那就一步一步推进下去，我相信想法会越来越清晰的。很多事情，或许只是想，是想不出来的，只有去做的时候，思路才逐渐变得明朗起来，加油！</p>
<p>就像扎克伯格曾经在一次演讲中说到：</p>
<blockquote>
<p>但我想告诉你一个秘密：没有人从一开始就知道如何做，想法最开始，并不完全成型，只有当你不断推进时，它才变得逐渐清晰，你需要开始努力。</p>
</blockquote>
<p></p>
<p></p>
<p></p>


]]></content:encoded>
    </item>
    <item>
      <title>搭建一个全自动发布的超牛博客</title>
      <link>https://blueberry-universe.cn/2024-10-30-00/</link>
      <guid>https://blueberry-universe.cn/2024-10-30-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml">搭建一个全自动发布的超牛博客</source>
      <description>搭建一个全自动发布的超牛博客
前几天在公众号看到了 鱼皮 发的一篇文章，讲了他的文档博客是如何搭建的，建议看本文之前可以先看看他的文章，鱼皮文章的传送门：
https://mp.weixin.qq.com/s/xti5QUoh6UOuCs81uNfJHA
本着好奇的心，我就去折腾了一番，最后我发现，虽然已经很简化了！但还是太麻烦了，毕竟我是真的懒，我更...</description>
      <content:encoded><![CDATA[
<p>前几天在公众号看到了 鱼皮 发的一篇文章，讲了他的文档博客是如何搭建的，建议看本文之前可以先看看他的文章，鱼皮文章的传送门：</p>
<p>https://mp.weixin.qq.com/s/xti5QUoh6UOuCs81uNfJHA</p>
<p>本着好奇的心，我就去折腾了一番，最后我发现，虽然已经很简化了！但还是太麻烦了，毕竟我是真的懒，我更希望，我在本地写好内容之后，我根本不需要去我的博客手动添加一篇文章就能让它自己显示出来。</p>
<p>为了，我做了一套自动化工具来完成这件事情，那么这篇文章就是在 鱼皮 给出的方法的基础上添加了一些自动化工具，实现博客的全自动发布。</p>
<h2>1、蓝莓的博客已经上线了</h2>
<p>我早在几个月前就已经使用 Typecho 做了一个博客，但总是感觉不太好用，没办法将所有的内容做成的更有体系化。文档类型的博客让我觉得是一个非常好的选择，所以最后采用了  vuepress 重新改造了蓝莓的小站。</p>
<p>传送门:https://blueberry-universe.cn</p>
<ol>
<li>购买域名</li>
<li>完成 ICP 备案</li>
<li>完成公安备案</li>
<li>使用 vuepress 生成博客的静态文件</li>
<li>采用 Nginx 对静态文件进行托管</li>
</ol>
<p>在我部署的过程中，是采用了 Nginx 进行静态文件托管的，当然，你也可以采取别的方法。</p>
<h2>2、获取博客的模板</h2>
<p>可以直接访问我的 github 代码仓，获取这套模板</p>
<p>https://github.com/teenager-lijh/cocoalgo/tree/template</p>
<p>直接下载 cocoalgo 代码仓的 template 分支即可</p>
<p>接下来，你就直接把这个代码上传到你要部署的服务器上就可以了，在这里我使用虚拟机进行演示，我的虚拟机本地 ip 为 <code>10.211.55.100</code></p>
<p>上传代码到虚拟机后，我们来看看 cocoalgo 里面都有什么</p>
<ol>
<li>所有的配置文件都在红色箭头所指向的 <code>.vuepress</code> 文件夹中</li>
<li>蓝色框框所框出来的是我博客中的主题，目前我的在线博客中共有 6 个主题</li>
<li>绿色箭头所指向的四个文件，是我做的 4 个自动化的处理工具</li>
</ol>
<p></p>
<p>来看看绿色箭头所指向的 4 个自动化处理工具都是做什么的</p>
<ol>
<li>fix_markdown.py : 由于我是用的 markdown 编辑工具是 typora，每次当我粘贴图片到 markdown 的时候，我会让它自动为我创建一个 assets 资源文件夹，然后它采用的相对路径是例如 <code>assets/images.jpg</code> 这样的形式，但是 vuepress 很不巧的不识别这种相对路径，如果改成 <code>./assets/images.jpg</code> 的形式就能够被 vuepress 识别并且正确渲染，所以我做了一个 fix_markdown.py 工具递归的对所有的 markdown 文件进行修改</li>
<li>resize_image_files.py : 这个工具是用来对图像进行缩放的，由于我的云服务器带宽特别小，而我的图片都太大啦，加载速度太慢。这个工具会对 <code>.vuepress/dist</code> 这个文件夹中所有的图像文件进行缩放并重新保存，缩放后的图像大小会保证在 400KB 以内</li>
<li>generate_config.py : 这个文件是全自动化的核心秘密，看过鱼皮的视频之后，你应该会知道，每次我们发布一篇文章之后都要在 .vuepress 中对相应的配置文件进行修改，但是现在，全都不用了！在 <code>cocoalgo</code> 文件夹中还有一个文件叫做 <code>config.list</code> 。这里面存储了当前的博客有几个主题，以及这几个主题在 cocolgo 目录中的位置。这个文件的内容我放在了下面，你可以看看。每一行都由三个元素构成，每个元素之间使用空格隔开，第一个元素表示了你的一个主题所存储的文章相对于 <code>cocoalgo</code> 的位置，由于我都是直接放在了 <code>cocoalgo</code> 目录中，所以第一个直接就写目录的名称即可，第二项内容你应该很眼熟，这个是每个主题中想要展示出来的文章要进行配置的配置文件，现在你不需要进行配置了，你只需要给出这个配置文件的名称即可（名字可以随意写，但是一定要以 .ts 结尾），第三项内容直接和第一项内容保持一致即可 （这里设置的是配置文件中 title 对应的配置项，你可以根据需求进行修改，或者直接和第一项保持一致）</li>
</ol>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line"># config.list 文件</span>
<span class="line">蓝莓随便扯 ideaSideBar.ts 蓝莓随便扯</span>
<span class="line">操作系统 osSideBar.ts 操作系统</span>
<span class="line">计算机网络 cnSideBar.ts 计算机网络</span>
<span class="line">力扣刷题 lcSideBar.ts 力扣刷题</span>
<span class="line">分布式系统 dsSideBar.ts 分布式系统</span>
<span class="line">Pythoner pythonerSideBar.ts Pythoner</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="4">
<li>最后就是 deploy.sh 这个工具了，<code>deploy.sh</code> 需要传递一个参数，这个参数是一个字符串，你需要告诉它，cocoalgo 本地代码仓所在的位置是哪里，然后 deploy.sh 会自动进入到该代码仓并且去拉取远程端的 main 分支到本地，如果发现远程端的 main 分支比本地更新了，那么 deploy.sh 会清除本地代码仓所有没有用的东西并恢复到最近的一条提交记录上，拉取远程端的内容覆盖本地。接着，deploy.sh 会调用 <code>npm docs:build</code> 命令生成静态文件到 <code>.vuepress</code> 目录中的 <code>dist</code> 目录中。</li>
</ol>
<p>接着，我们什么都不需要做了，如果我们使用了 Nginx 来对静态文件进行代理，那么，我们只需要让 Nginx 代理的静态文件目录始终指向 <code>cocoalgo/.vuepress/dist</code> 目录即可</p>
<p><strong>最重要的一点</strong></p>
<p>我相信你的主题肯定不会天天变吧，你只需要配置一下 <code>config.list</code> 文件就可以了。</p>
<p>只要我们在本地提交了代码到远程端，服务器上开一个定时任务，定时的执行 deploy.sh 就可以了，这样就可以实现定时自动检查并且发布的功能了。</p>
<h2>3、动手安装吧</h2>
<p>这里演示的 cocoalgo 是我自己的仓库，你需要下载我的代码，并且自己新建一个代码仓到 main 分支中，然后把我这里面除了 <code>cocoalgo/.git</code> 目录的内容外，全部拷贝过去，然后进行实验</p>
<ol>
<li>安装所依赖的工具，在这里你要和我的 node 以及 npm 的版本保持一致，这两项的安装很简单，我就不详细说了</li>
</ol>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:~/Lib/cocoalgo$ node -v</span>
<span class="line">v16.20.2</span>
<span class="line">blueberry@ubuntu:~/Lib/cocoalgo$ npm -v</span>
<span class="line">8.19.4</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="2">
<li>安装依赖包</li>
</ol>
<p>在这里下载的过程中可能很慢，你可以尝试使用国内的源进行安装，速度会快得多</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line"># 进入到 cocoalgo 执行如下命令</span>
<span class="line">npm i</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p></p>
<ol start="3">
<li>安装 Nginx 并配置</li>
</ol>
<p>我这里使用的 Nginx 的版本是 <code>1.26.2</code></p>
<p>首先去官网下载 Nginx 到服务器上，然后对它解压，解压之后我们可以看到这些内容</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/Downloads/nginx-1.26.2$ <span class="token function">ls</span> <span class="token parameter variable">-ltr</span></span>
<span class="line">total <span class="token number">780</span></span>
<span class="line">-rw-r--r-- <span class="token number">1</span> blueberry blueberry     <span class="token number">49</span> Aug <span class="token number">13</span>  <span class="token number">2019</span> README</span>
<span class="line">-rw-r--r-- <span class="token number">1</span> blueberry blueberry   <span class="token number">1397</span> Aug <span class="token number">13</span>  <span class="token number">2019</span> LICENSE</span>
<span class="line">-rwxr-xr-x <span class="token number">1</span> blueberry blueberry   <span class="token number">2502</span> Aug <span class="token number">13</span>  <span class="token number">2019</span> configure</span>
<span class="line">-rw-r--r-- <span class="token number">1</span> blueberry blueberry <span class="token number">452171</span> Aug <span class="token number">13</span>  <span class="token number">2019</span> CHANGES.ru</span>
<span class="line">-rw-r--r-- <span class="token number">1</span> blueberry blueberry <span class="token number">296463</span> Aug <span class="token number">13</span>  <span class="token number">2019</span> CHANGES</span>
<span class="line">drwxr-xr-x <span class="token number">2</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">28</span> 08:25 <span class="token function">man</span></span>
<span class="line">drwxr-xr-x <span class="token number">2</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">28</span> 08:25 html</span>
<span class="line">drwxr-xr-x <span class="token number">9</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">28</span> 08:25 src</span>
<span class="line">drwxr-xr-x <span class="token number">4</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">28</span> 08:25 contrib</span>
<span class="line">drwxr-xr-x <span class="token number">2</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">28</span> 08:25 conf</span>
<span class="line">drwxr-xr-x <span class="token number">6</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">28</span> 08:25 auto</span>
<span class="line">drwxrwxr-x <span class="token number">3</span> blueberry blueberry   <span class="token number">4096</span> Sep <span class="token number">30</span> <span class="token number">10</span>:36 objs</span>
<span class="line">-rw-rw-r-- <span class="token number">1</span> blueberry blueberry    <span class="token number">355</span> Sep <span class="token number">30</span> <span class="token number">10</span>:36 Makefile</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>生成 Makefile</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">blueberry@ubuntu:~/Downloads/nginx-1.26.2$ ./configure <span class="token parameter variable">--prefix</span><span class="token operator">=</span>/usr/local/nginx --pid-path<span class="token operator">=</span>/var/run/nginx/nginx.pid --lock-path<span class="token operator">=</span>/var/lock/nginx.lock --error-log-path<span class="token operator">=</span>/var/log/nginx/error.log --http-log-path<span class="token operator">=</span>/var/log/nginx/access.log --with-http_gzip_static_module --http-client-body-temp-path<span class="token operator">=</span>/var/temp/nginx/proxy --http-fastcgi-temp-path<span class="token operator">=</span>/var/temp/nginx/fastcgi --http-uwsgi-temp-path<span class="token operator">=</span>/var/temp/nginx/uwsgi --http-scgi-temp-path<span class="token operator">=</span>/var/temp/nginx/scgi --with-http_ssl_module --with-http_image_filter_module</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>编译并安装</strong></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:~/Downloads/nginx-1.26.2$ make</span>
<span class="line">blueberry@ubuntu:~/Downloads/nginx-1.26.2$ make install</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>完成上述命令之后，我们就完成了 Nginx 的安装，根据 <code>./configure</code> 中的配置，我们可以知道 <code>Nginx</code> 被安装到了 <code>/usr/local/nginx</code> 这个位置。</p>
<p><strong>修改 Nginx 的配置文件</strong></p>
<p>我们进入到 <code>/usr/local/nginx/conf</code> 并编辑 <code>nginx.conf</code> 文件（配置文件中的 user 这个后面写你的 cocoalgo 所在用户目录的用户名，这个很重要，不然会出现一些权限问题）</p>
<p>如果你不配置 https 的话 配置文件这么写</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line"></span>
<span class="line">user  blueberry;</span>
<span class="line">worker_processes  2;</span>
<span class="line"></span>
<span class="line">#error_log  logs/error.log;</span>
<span class="line">#error_log  logs/error.log  notice;</span>
<span class="line">#error_log  logs/error.log  info;</span>
<span class="line"></span>
<span class="line">#pid        logs/nginx.pid;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">events {</span>
<span class="line">    worker_connections  1024;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">http {</span>
<span class="line">    include       mime.types;</span>
<span class="line">    default_type  application/octet-stream;</span>
<span class="line">    sendfile        on;</span>
<span class="line">    keepalive_timeout  65;</span>
<span class="line"></span>
<span class="line">    gzip  on;</span>
<span class="line"></span>
<span class="line">    # 小于 1B 的文件不会压缩</span>
<span class="line">    gzip_min_length 1;</span>
<span class="line"></span>
<span class="line">    # 压缩比 可以设置 1-9</span>
<span class="line">    # 数值越大 压缩级别越大 占用的 CPU 越多</span>
<span class="line">    gzip_comp_level 3;</span>
<span class="line"></span>
<span class="line">    # 压缩文件的类型</span>
<span class="line">    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/json;</span>
<span class="line"></span>
<span class="line">    server {</span>
<span class="line">        listen       80;</span>
<span class="line">        # 这里写你的博客的域名 没有域名就写虚拟机的 ip</span>
<span class="line">        server_name  blueberry-universe.cn;</span>
<span class="line"></span>
<span class="line">        #charset koi8-r;</span>
<span class="line"></span>
<span class="line">        #access_log  logs/host.access.log  main;</span>
<span class="line"></span>
<span class="line">        location / {</span>
<span class="line">            root   /root/Library/cocoalgo/.vuepress/dist;</span>
<span class="line">            index  index.html index.htm;</span>
<span class="line">	}</span>
<span class="line"></span>
<span class="line">        error_page   500 502 503 504  /50x.html;</span>
<span class="line">        location = /50x.html {</span>
<span class="line">            root   html;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你配置 https 的话，配置文件这样写</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">user  blueberry;</span>
<span class="line">worker_processes  2;</span>
<span class="line"></span>
<span class="line">#error_log  logs/error.log;</span>
<span class="line">#error_log  logs/error.log  notice;</span>
<span class="line">#error_log  logs/error.log  info;</span>
<span class="line"></span>
<span class="line">#pid        logs/nginx.pid;</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">events {</span>
<span class="line">    worker_connections  1024;</span>
<span class="line">}</span>
<span class="line"></span>
<span class="line"></span>
<span class="line">http {</span>
<span class="line">    include       mime.types;</span>
<span class="line">    default_type  application/octet-stream;</span>
<span class="line">    sendfile        on;</span>
<span class="line">    keepalive_timeout  65;</span>
<span class="line"></span>
<span class="line">    gzip  on;</span>
<span class="line"></span>
<span class="line">    # 小于 1B 的文件不会压缩</span>
<span class="line">    gzip_min_length 1;</span>
<span class="line"></span>
<span class="line">    # 压缩比 可以设置 1-9</span>
<span class="line">    # 数值越大 压缩级别越大 占用的 CPU 越多</span>
<span class="line">    gzip_comp_level 3;</span>
<span class="line"></span>
<span class="line">    # 压缩文件的类型</span>
<span class="line">    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/json;</span>
<span class="line"></span>
<span class="line">    server {</span>
<span class="line">        listen       80;</span>
<span class="line">        # 这里写你的博客的域名 没有域名就写虚拟机的 ip</span>
<span class="line">        server_name  blueberry-universe.cn;</span>
<span class="line"></span>
<span class="line">        #charset koi8-r;</span>
<span class="line"></span>
<span class="line">        #access_log  logs/host.access.log  main;</span>
<span class="line"></span>
<span class="line">        location / {</span>
<span class="line">        	# 在这里配置你的 dist 文件夹的路径</span>
<span class="line">            root   /home/blueberry/Lib/cocoalgo/.vuepress/dist;</span>
<span class="line">            index  index.html index.htm;</span>
<span class="line">	}</span>
<span class="line"></span>
<span class="line">        error_page   500 502 503 504  /50x.html;</span>
<span class="line">        location = /50x.html {</span>
<span class="line">            root   html;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line"></span>
<span class="line">    server {</span>
<span class="line">        listen 443 ssl;</span>
<span class="line">        server_name blueberry-universe.cn; </span>
<span class="line"></span>
<span class="line">        # 配置 ssl 证书</span>
<span class="line">        ssl_certificate	/usr/local/nginx/conf/blueberry-universe/blueberry-universe.cn_bundle.crt;</span>
<span class="line">        # 配置证书秘钥</span>
<span class="line">        ssl_certificate_key	/usr/local/nginx/conf/blueberry-universe/blueberry-universe.cn.key;</span>
<span class="line">        # ssl 会话 cache</span>
<span class="line">        ssl_session_cache	shared:SSL:1m;</span>
<span class="line">        # ssl 会话超时时间</span>
<span class="line">        ssl_session_timeout	5m;</span>
<span class="line"></span>
<span class="line">        # 配置加密套件 写法遵循 openssl 标准</span>
<span class="line">        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</span>
<span class="line">        ssl_ciphers HIGH:!aNULL:!MD5:!RC4:!DHE;</span>
<span class="line">	ssl_prefer_server_ciphers on;</span>
<span class="line"></span>
<span class="line">        location / {</span>
<span class="line">            proxy_pass http://blueberry-universe.cn;</span>
<span class="line">        }</span>
<span class="line">    }</span>
<span class="line">}</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>4、让它跑起来</h2>
<p>在 github 建你自己的仓库这些，就你自己来完成好啦，记得在你的服务器上配置上 github 代码仓的 ssh 对应的私钥，这样才能让 deploy.sh 有权限去拉取远程端的代码的。</p>
<p><strong>配置定时任务</strong></p>
<p>使用 <code>crontab</code> 配置定时任务，让 <code>deploy.sh</code> 每分钟执行一次，来看看远程端的代码是不是更新了，当然啦，你可以把执行的频率设置的更长一些</p>
<p><code>crontab -l</code> 查看当前都有哪些定时任务</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:~/Downloads/nginx-1.26.2$ crontab -l</span>
<span class="line">*/1 * * * * /home/blueberry/Lib/cocoalgo/deploy/deploy.sh /home/blueberry/Lib/cocoalgo >> /home/blueberry/Lib/update.log 2>&amp;1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>这是我已经添加的定时任务，你可以使用 <code>crontab -e</code> 命令编辑这个定时任务的列表，然后把你的定时任务添加进去就可以了，添加的过程和使用 <code>vim</code> 操作文件是一样的，添加完成后使用 <code>:wq</code> 保存并退出即可</p>
<p>在定时任务重你可以看到 <code>deploy.sh</code> 后面传入的参数 <code>/home/blueberry/Lib/cocoalgo</code> 就是服务器上的本地代码仓的所在位置，我们需要把这个东西告诉 <code>deploy.sh</code> 才可以，在这里我把 <code>deploy.sh</code> 每次运行后输出的日志保存在了 <code>~/Lib</code> 目录中的 <code>update.log</code> 文件中</p>
<p><strong>启动 Nginx</strong></p>
<p>只需要这样，Nginx 就会默认使用 <code>nginx.conf</code> 启动啦！</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">blueberry@ubuntu:/usr/local/nginx/sbin$ pwd</span>
<span class="line">/usr/local/nginx/sbin</span>
<span class="line">blueberry@ubuntu:/usr/local/nginx/sbin$ ls</span>
<span class="line">nginx</span>
<span class="line">blueberry@ubuntu:/usr/local/nginx/sbin$ ./nginx</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>注意事项</strong></p>
<p>当然啦，在第一次启动的时候，你可以先在 <code>cocoalgo</code> 目录下先手动的运行 <code>npm run docs:build</code> 命令生成一次配置文件，后续，每次远程端有新的文章上去之后，让它自己去拉取并且更新即可</p>


]]></content:encoded>
    </item>
    <item>
      <title></title>
      <link>https://blueberry-universe.cn/2024-05-07-00/</link>
      <guid>https://blueberry-universe.cn/2024-05-07-00/</guid>
      <source url="https://blueberry-universe.cn/rss.xml"></source>
      <description>彻底搞懂虚拟网络搭建
你好啊，我是蓝莓，最近在研究和计算机网络的内容，就和大家分享一下
用过 docker 的小伙伴应该能领会到  docker 在部署一些应用时真的是十分方便啊，那么我们的侧重点在于 docker 在宿主机是如何访问外网的，这里所指的外网是指宿主机外部的网络。本文中所介绍的虚拟网络搭建方式与 docker 所应用的是非常相似的，但是本...</description>
      <content:encoded><![CDATA[<h2>彻底搞懂虚拟网络搭建</h2>
<p>你好啊，我是蓝莓，最近在研究和计算机网络的内容，就和大家分享一下</p>
<p>用过 docker 的小伙伴应该能领会到  docker 在部署一些应用时真的是十分方便啊，那么我们的侧重点在于 docker 在宿主机是如何访问外网的，这里所指的外网是指宿主机外部的网络。本文中所介绍的虚拟网络搭建方式与 docker 所应用的是非常相似的，但是本文并不涉及任何和 docker 相关的内容。</p>
<p>目标：</p>
<ol>
<li>使用 QEMU 创建虚拟机</li>
<li>创建虚拟网桥，为虚拟网桥配置 ip</li>
<li>为虚拟机创建虚拟网卡并配置 ip</li>
<li>为虚拟机配置路由表</li>
<li>使用Linux做数据转发</li>
<li>使用 iptables 为宿主机提供 NAT 功能</li>
<li>配置 DNS 服务器</li>
</ol>
<h2>1 QEMU 创建虚拟机</h2>
<p>我的宿主机是一台真实的物理机器，安装了 <code>22.04.1-Ubuntu</code> 系统</p>
<p>安装 QEMU 的方法也是很简单的，在这里就不详细说明了，可以直接搜索 ubuntu 安装 QEMU 会有非常多的安装教程可供参考。</p>
<p><strong>下载系统镜像</strong></p>
<p>虽然我的物理机器是 <code>22.04.1-Ubuntu</code> ，但是我在创建虚拟机的时候采用了<code>ubuntu-18.04.6-live-server-amd64.iso</code></p>
<p>镜像下载地址：https://releases.ubuntu.com/18.04.6/ubuntu-18.04.6-live-server-amd64.iso</p>
<p>下载好系统镜像后，我将该镜像放在如下位置</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"> /home/blueberry/Downloads/ubuntu-18.04.6-live-server-amd64.iso</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>创建虚拟磁盘</strong></p>
<p>在这篇文章中一共需要使用 QEMU 创建两台虚拟机 <code>ubuntu</code> 和 <code>ubuntu2</code>，为此，也应该创建两个虚拟磁盘供它使用。先回到家目录，然后创建一个文件夹 <code>qemu</code> 用来存放稍后要创建的虚拟磁盘，随后我们分别创建两个大小为 <code>40G</code> 的虚拟磁盘 ubuntu.img 和 ubuntu2.img</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token builtin class-name">cd</span> ~</span>
<span class="line"><span class="token function">mkdir</span> qemu</span>
<span class="line">qemu-img create <span class="token parameter variable">-f</span> qcow2 ubuntu.img 40G</span>
<span class="line">qemu-img create <span class="token parameter variable">-f</span> qcow2 ubuntu2.img 40G</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>安装虚拟机 ubuntu</strong></p>
<p>接下来我们就分别安装两台虚拟机</p>
<p>安装 ubuntu 虚拟机，简单介绍下几个参数：</p>
<ul>
<li>-name: 指定虚拟机的名字</li>
<li>-m: 指定虚拟机的 RAM 内存大小为 2048M</li>
<li>-hda: 指定虚拟机所使用的虚拟磁盘所在路径</li>
<li>-cdrom: 指定该虚拟机所使用的镜像所在路径</li>
<li>-boot: 虚拟机启动方式，这里选择 d 则是从 cdrom 这里启动</li>
<li>-vnc: 打开一个 vnc 服务，供我们安装虚拟机使用，这里的 19 代表的是 5919 端口，默认是从 5900 端口开始使用的</li>
</ul>
<p>其他的参数就照着写就好了</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">qemu-system-x86_64 <span class="token punctuation">\</span></span>
<span class="line">        -enable-kvm <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-name</span> ubuntu <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-m</span> <span class="token number">2048</span> <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-hda</span> /home/blueberry/qemu/ubuntu.img <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-cdrom</span> /home/blueberry/Downloads/ubuntu-18.04.6-live-server-amd64.iso <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-boot</span> d <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-vnc</span> :19 <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-cpu</span> <span class="token function">host</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接下来，你还需要一个 vnc 客户端作为你的虚拟机屏幕，可以直接使用 <code>vnc viewer</code> 作为客户端，官网传送门：</p>
<p>https://www.realvnc.com/en/connect/download/viewer/</p>
<p><strong>使用 vnc 连接虚拟机</strong></p>
<p>打开 <code>vnc viewer</code> 后，直接在地址栏输入宿主机的 <code>ip</code> 地址以及 <code>vnc</code> 服务对应的端口号之后连接即可</p>
<p></p>
<p>打开后，你只需要按照正常的操作系统安装流程进程安装就可以了</p>
<p></p>
<p><strong>安装虚拟机 ubuntu2</strong></p>
<p>好啦，安装 <code>ubuntu2</code> 的过程是一样的，那你只需要适当的调整参数之后，进行安装就可以了</p>
<h2>2 创建虚拟网桥</h2>
<p>接下来，我们在宿主机创建一个网桥 <code>br0</code> 并且为该网桥分配 ip 地址</p>
<p>我们先来查看一下宿主机中当前的网络接口情况，可以发现，我的物理网卡对应的名称是 <code>enp2s0</code></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">ifconfig</span></span>
<span class="line">enp2s0: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">416</span><span class="token operator"><span class="token file-descriptor important">3</span>&lt;</span>UP,BROADCAST,RUNNING,MULTICAST<span class="token operator">></span>  mtu <span class="token number">1500</span></span>
<span class="line">        inet <span class="token number">192.168</span>.1.184  netmask <span class="token number">255.255</span>.255.0  broadcast <span class="token number">192.168</span>.1.255</span>
<span class="line">        inet6 fe80::8a4:75b8:a07:2a83  prefixlen <span class="token number">64</span>  scopeid 0x2<span class="token operator"><span class="token file-descriptor important">0</span>&lt;</span>link<span class="token operator">></span></span>
<span class="line">        ether <span class="token number">94</span>:c6:91:61:10:ec  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Ethernet<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">354</span>  bytes <span class="token number">79267</span> <span class="token punctuation">(</span><span class="token number">79.2</span> KB<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">202</span>  bytes <span class="token number">35860</span> <span class="token punctuation">(</span><span class="token number">35.8</span> KB<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">lo: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">7</span><span class="token operator"><span class="token file-descriptor important">3</span>&lt;</span>UP,LOOPBACK,RUNNING<span class="token operator">></span>  mtu <span class="token number">65536</span></span>
<span class="line">        inet <span class="token number">127.0</span>.0.1  netmask <span class="token number">255.0</span>.0.0</span>
<span class="line">        inet6 ::1  prefixlen <span class="token number">128</span>  scopeid 0x1<span class="token operator"><span class="token file-descriptor important">0</span>&lt;</span>host<span class="token operator">></span></span>
<span class="line">        loop  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Local Loopback<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">154</span>  bytes <span class="token number">14234</span> <span class="token punctuation">(</span><span class="token number">14.2</span> KB<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">154</span>  bytes <span class="token number">14234</span> <span class="token punctuation">(</span><span class="token number">14.2</span> KB<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>创建网桥 br0</strong></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> brctl addbr br0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>创建两个网桥上的接口</strong></p>
<p>使用命令 <code>tunctl -b</code> 创建 tap device，默认的名字分别为 <code>tap0</code> 和 <code>tap1</code>，我目前理解的是，我们创建 tap device 然后再把这个东西给绑在网桥 <code>br0</code> 上就好像是让这个网桥拥有了两个插口，这样，我们可以在这个 网桥上插两台计算机设备，这个理解可能有点牵强，欢迎大佬进行指正</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> tunctl <span class="token parameter variable">-b</span></span>
<span class="line">tap0</span>
<span class="line">➜  ~ <span class="token function">sudo</span> tunctl <span class="token parameter variable">-b</span></span>
<span class="line">tap1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>查看当前的网络接口</strong></p>
<p>我们可以通过 <code>ip link show</code> 来查看网络接口，然而使用 <code>ifconfig</code> 是没办法看到没有启动的网络接口的</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">ip</span> <span class="token function">link</span> show</span>
<span class="line"><span class="token number">1</span>: lo: <span class="token operator">&lt;</span>LOOPBACK,UP,LOWER_UP<span class="token operator">></span> mtu <span class="token number">65536</span> qdisc noqueue state UNKNOWN mode DEFAULT group default qlen <span class="token number">1000</span></span>
<span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span>
<span class="line"><span class="token number">2</span>: enp2s0: <span class="token operator">&lt;</span>BROADCAST,MULTICAST,UP,LOWER_UP<span class="token operator">></span> mtu <span class="token number">1500</span> qdisc fq_codel state UP mode DEFAULT group default qlen <span class="token number">1000</span></span>
<span class="line">    link/ether <span class="token number">94</span>:c6:91:61:10:ec brd ff:ff:ff:ff:ff:ff</span>
<span class="line"><span class="token number">3</span>: virbr0: <span class="token operator">&lt;</span>NO-CARRIER,BROADCAST,MULTICAST,UP<span class="token operator">></span> mtu <span class="token number">1500</span> qdisc noqueue state DOWN mode DEFAULT group default qlen <span class="token number">1000</span></span>
<span class="line">    link/ether <span class="token number">52</span>:54:00:10:65:68 brd ff:ff:ff:ff:ff:ff</span>
<span class="line"><span class="token number">4</span>: br0: <span class="token operator">&lt;</span>BROADCAST,MULTICAST<span class="token operator">></span> mtu <span class="token number">1500</span> qdisc noop state DOWN mode DEFAULT group default qlen <span class="token number">1000</span></span>
<span class="line">    link/ether e2:eb:19:ae:67:37 brd ff:ff:ff:ff:ff:ff</span>
<span class="line"><span class="token number">5</span>: tap0: <span class="token operator">&lt;</span>BROADCAST,MULTICAST<span class="token operator">></span> mtu <span class="token number">1500</span> qdisc noop state DOWN mode DEFAULT group default qlen <span class="token number">1000</span></span>
<span class="line">    link/ether 2a:34:1e:9f:42:d2 brd ff:ff:ff:ff:ff:ff</span>
<span class="line"><span class="token number">6</span>: tap1: <span class="token operator">&lt;</span>BROADCAST,MULTICAST<span class="token operator">></span> mtu <span class="token number">1500</span> qdisc noop state DOWN mode DEFAULT group default qlen <span class="token number">1000</span></span>
<span class="line">    link/ether d6:cd:ae:4c:b2:b8 brd ff:ff:ff:ff:ff:ff</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>绑定 tap device 到 br0</strong></p>
<p>通过下面的方法进行绑定</p>
<p><code>addif</code> 代表的是 <code>add interface</code>，添加接口</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> brctl addif br0 tap0</span>
<span class="line">➜  ~ <span class="token function">sudo</span> brctl addif br0 tap1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>另外的你也可以通过 <code>ip</code> 命令中所提供的工具完成这个操作，这两种操作达到的效果都是一样的，这里的 <code>link</code> 代表的是 <code>link layer</code> 链路层</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> <span class="token function">ip</span> <span class="token function">link</span> <span class="token builtin class-name">set</span> tap0 master br0</span>
<span class="line">➜  ~ <span class="token function">sudo</span> <span class="token function">ip</span> <span class="token function">link</span> <span class="token builtin class-name">set</span> tap1 master br0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>以上两种方式你选择其中一种就可以了</p>
<p><strong>查看网桥的接口情况</strong></p>
<p>这时候我们就可以看到 <code>tap0</code> 和 <code>tap1</code> 已经成功捆绑在 <code>br0</code> 网桥上了</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ brctl show</span>
<span class="line">bridge name	bridge <span class="token function">id</span>		    STP enabled    interfaces</span>
<span class="line">br0		<span class="token number">8000</span>.e2eb19ae6737	    no		       tap0</span>
<span class="line">							                   tap1</span>
<span class="line">virbr0		<span class="token number">8000.525400106568</span>	<span class="token function">yes</span>	</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>启动网络接口</strong></p>
<p>我们分别启动刚才创建的三个虚拟设备，然后再使用 <code>ifconfig</code> 查看网络接口的情况，这时候我们查看到刚才创建好的网络设备全部都启动了</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> <span class="token function">ip</span> <span class="token function">link</span> <span class="token builtin class-name">set</span> br0 up</span>
<span class="line">➜  ~ <span class="token function">sudo</span> <span class="token function">ip</span> <span class="token function">link</span> <span class="token builtin class-name">set</span> tap0 up</span>
<span class="line">➜  ~ <span class="token function">sudo</span> <span class="token function">ip</span> <span class="token function">link</span> <span class="token builtin class-name">set</span> tap1 up</span>
<span class="line">➜  ~ <span class="token function">ifconfig</span></span>
<span class="line">br0: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">409</span><span class="token operator"><span class="token file-descriptor important">9</span>&lt;</span>UP,BROADCAST,MULTICAST<span class="token operator">></span>  mtu <span class="token number">1500</span></span>
<span class="line">        ether e2:eb:19:ae:67:37  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Ethernet<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">0</span>  bytes <span class="token number">0</span> <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">0</span>  bytes <span class="token number">0</span> <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">enp2s0: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">416</span><span class="token operator"><span class="token file-descriptor important">3</span>&lt;</span>UP,BROADCAST,RUNNING,MULTICAST<span class="token operator">></span>  mtu <span class="token number">1500</span></span>
<span class="line">        inet <span class="token number">192.168</span>.1.184  netmask <span class="token number">255.255</span>.255.0  broadcast <span class="token number">192.168</span>.1.255</span>
<span class="line">        inet6 fe80::8a4:75b8:a07:2a83  prefixlen <span class="token number">64</span>  scopeid 0x2<span class="token operator"><span class="token file-descriptor important">0</span>&lt;</span>link<span class="token operator">></span></span>
<span class="line">        ether <span class="token number">94</span>:c6:91:61:10:ec  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Ethernet<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">3059</span>  bytes <span class="token number">429509</span> <span class="token punctuation">(</span><span class="token number">429.5</span> KB<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">1050</span>  bytes <span class="token number">136524</span> <span class="token punctuation">(</span><span class="token number">136.5</span> KB<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">lo: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">7</span><span class="token operator"><span class="token file-descriptor important">3</span>&lt;</span>UP,LOOPBACK,RUNNING<span class="token operator">></span>  mtu <span class="token number">65536</span></span>
<span class="line">        inet <span class="token number">127.0</span>.0.1  netmask <span class="token number">255.0</span>.0.0</span>
<span class="line">        inet6 ::1  prefixlen <span class="token number">128</span>  scopeid 0x1<span class="token operator"><span class="token file-descriptor important">0</span>&lt;</span>host<span class="token operator">></span></span>
<span class="line">        loop  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Local Loopback<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">213</span>  bytes <span class="token number">19837</span> <span class="token punctuation">(</span><span class="token number">19.8</span> KB<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">213</span>  bytes <span class="token number">19837</span> <span class="token punctuation">(</span><span class="token number">19.8</span> KB<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">tap0: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">409</span><span class="token operator"><span class="token file-descriptor important">9</span>&lt;</span>UP,BROADCAST,MULTICAST<span class="token operator">></span>  mtu <span class="token number">1500</span></span>
<span class="line">        ether 2a:34:1e:9f:42:d2  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Ethernet<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">0</span>  bytes <span class="token number">0</span> <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">0</span>  bytes <span class="token number">0</span> <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span>
<span class="line">tap1: <span class="token assign-left variable">flags</span><span class="token operator">=</span><span class="token number">409</span><span class="token operator"><span class="token file-descriptor important">9</span>&lt;</span>UP,BROADCAST,MULTICAST<span class="token operator">></span>  mtu <span class="token number">1500</span></span>
<span class="line">        ether d6:cd:ae:4c:b2:b8  txqueuelen <span class="token number">1000</span>  <span class="token punctuation">(</span>Ethernet<span class="token punctuation">)</span></span>
<span class="line">        RX packets <span class="token number">0</span>  bytes <span class="token number">0</span> <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span></span>
<span class="line">        RX errors <span class="token number">0</span>  dropped <span class="token number">0</span>  overruns <span class="token number">0</span>  frame <span class="token number">0</span></span>
<span class="line">        TX packets <span class="token number">0</span>  bytes <span class="token number">0</span> <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span></span>
<span class="line">        TX errors <span class="token number">0</span>  dropped <span class="token number">0</span> overruns <span class="token number">0</span>  carrier <span class="token number">0</span>  collisions <span class="token number">0</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>为网桥 br0 配置 ip</strong></p>
<p>在这里将 <code>br0</code> 的 ip 设置为 <code>192.168.166.1</code> 且其中的 24 就是代表设置子网掩码为 <code>255.255.255.0</code></p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">➜  ~ sudo ifconfig br0 192.168.166.1/24 </span>
<span class="line">➜  ~ ifconfig</span>
<span class="line">br0: flags=4099&lt;UP,BROADCAST,MULTICAST>  mtu 1500</span>
<span class="line">        inet 192.168.166.1  netmask 255.255.255.0  broadcast 192.168.166.255</span>
<span class="line">        ether e2:eb:19:ae:67:37  txqueuelen 1000  (Ethernet)</span>
<span class="line">        RX packets 0  bytes 0 (0.0 B)</span>
<span class="line">        RX errors 0  dropped 0  overruns 0  frame 0</span>
<span class="line">        TX packets 0  bytes 0 (0.0 B)</span>
<span class="line">        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>3 为虚拟机创建虚拟网卡并配置 ip</h2>
<p>刚才我们已经安装完成了虚拟机，那么再次启动的时候，你就不需要再挂在那个系统的镜像文件了，我们启动虚拟机的时候使用如下的命令进行启动</p>
<p><strong>启动 ubuntu</strong></p>
<p>之前没讲过的两行参数代表的是，我们要为这台虚拟机虚拟出来一张网卡，并且指定该虚拟网卡的 <code>mac</code> 地址为 <code>52:54:00:12:34:10</code>，另外我们要将该网卡插在 <code>br0</code> 网桥的 <code>tap0</code> 这个接口上</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> qemu-system-x86_64 <span class="token punctuation">\</span></span>
<span class="line">        -enable-kvm <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-name</span> ubuntu <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-m</span> <span class="token number">2048</span> <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-hda</span> /home/blueberry/qemu/ubuntu.img <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-vnc</span> :19 <span class="token parameter variable">-cpu</span> <span class="token function">host</span> <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-net</span> nic,macaddr<span class="token operator">=</span><span class="token number">52</span>:54:00:12:34:10,model<span class="token operator">=</span>virtio <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-net</span> tap,ifname<span class="token operator">=</span>tap0,script<span class="token operator">=</span>no,downscript<span class="token operator">=</span>no</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>启动 ubuntu2</strong></p>
<p>类似的，我们通过如下命令启动 <code>ubuntu2</code> 虚拟机</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> qemu-system-x86_64 <span class="token punctuation">\</span></span>
<span class="line">        -enable-kvm <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-name</span> ubuntu <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-m</span> <span class="token number">2048</span> <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-hda</span> /home/blueberry/qemu/ubuntu2.img <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-vnc</span> :29 <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-cpu</span> <span class="token function">host</span> <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-net</span> nic,macaddr<span class="token operator">=</span><span class="token number">52</span>:54:00:12:34:20,model<span class="token operator">=</span>virtio <span class="token punctuation">\</span></span>
<span class="line">        <span class="token parameter variable">-net</span> tap,ifname<span class="token operator">=</span>tap1,script<span class="token operator">=</span>no,downscript<span class="token operator">=</span>no</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当我们启动了这两台虚拟机之后，我们就可以使用 <code>vnc</code> 客户端分别对两台虚拟机进行连接了</p>
<p><strong>为 ubuntu 的网卡配置 ip</strong></p>
<p>在为虚拟机的网卡配置 <code>ip</code> 的时候，一定要注意，该网卡的 <code>ip</code> 需要和我们的网桥所配置的 <code>ip</code> 处于同一个网段内</p>
<p>先试用 <code>ifconfig</code> 查看到这台虚拟机的网卡的名称是 <code>ens3</code>，然后为该网卡设置一个 <code>ip: 192.169.166.100</code></p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> <span class="token function">ifconfig</span> ens3 <span class="token number">192.169</span>.166.100</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p>这时候，我们使用 <code>ping</code> 命令来看一下能不能在虚拟机内部与网桥 <code>br0</code> 进行通信</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">ping 192.168.166.1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p><strong>为 ubuntu2 的网卡配置 ip</strong></p>
<p>类似的，我们再为 <code>ubuntu2</code> 的网卡配置 <code>ip</code>，经过检查后，说明该虚拟机 <code>ubuntu2</code> 也是可以与网桥 <code>br0</code> 进行通信的</p>
<p></p>
<p>到此位置，位于同一个网桥上的虚拟机已经可以相互通信了，我在 <code>ubuntu2</code> 虚拟机上 <code>ping</code> ubuntu 虚拟机，结果如下：</p>
<p></p>
<h2>4 为虚拟机配置路由表</h2>
<p>为什么还要为虚拟机配置路由表呢？现在两台虚拟机不是已经能通信了吗？先来看一下我所处的网络结构：</p>
<p></p>
<p>尽管两台虚拟机已经可以正常通信了，但是我们现在可以尝试 <code>ping</code> 一下宿主机的 <code>ip</code> 以及与宿主机在同一个网段上的其他的机器</p>
<p>在 <code>ubuntu</code> 虚拟机上进行尝试，我们可以发现 <code>192.168.1.191</code> 是不可达的。我们从网络结构的拓扑图中可以看出虚拟网桥和外部的网络根本就是断开的嘛。这怎么可能让他们相互通信呢，这只是其中一个原因。另外一个原因是，路由表还需要进行配。</p>
<p></p>
<p><strong>查看路由表</strong></p>
<p>通过如下命令查看路由表：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">route <span class="token parameter variable">-n</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p>我们可以发现，路由表里面只有网段为 <code>192.168.166/24</code> 的路由规则，而网段为 <code>192.168.1.0/24</code> 的路由规则根本就不存在嘛，那我们不如直接配置一个默认的路由，其他的所有 <code>ip</code> 的寻址都通过虚拟机的网卡 <code>ens3</code> 将数据发出并且是发送到网桥那里，网桥的 ip 为 <code>192.168.166.1</code></p>
<p><strong>添加默认路由</strong></p>
<p>通过如下命令，我们添加一条默认路由到虚拟机 <code>ubuntu</code> 的路由表中</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> route <span class="token function">add</span> default gw <span class="token number">192.168</span>.166.1</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p>这时候我们再次使用 <code>ping</code> 命令进行测试，与上次不同的是，这次并没有直接显示网络不可达而是在等待网络返回响应，由于网桥那边和外界的网络是断开的，所以仅仅是添加了路由还不够</p>
<div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text"><pre><code class="language-text"><span class="line">ping 192.168.1.191</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<h2>5 使用 Linux 做数据转发</h2>
<p>对于 linux 系统而言，它是能够收到虚拟网桥 <code>br0</code> 的数据包的，因此，我们可以通过 <code>linux</code> 操作系统作为桥梁，将 <code>br0</code> 网桥的数据包转发到宿主机的网卡 <code>enp2s0</code> 上，这样一来，我们就可以将虚拟机内部的数据包真实的发送出去了</p>
<p>我们通过下面两个命令来打开 <code>linux</code> 的这个功能</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> <span class="token function">sysctl</span> <span class="token assign-left variable">net.ipv4.conf.all.forwarding</span><span class="token operator">=</span><span class="token number">1</span></span>
<span class="line">net.ipv4.conf.all.forwarding <span class="token operator">=</span> <span class="token number">1</span></span>
<span class="line">➜  ~ <span class="token function">sudo</span> iptables <span class="token parameter variable">-P</span> FORWARD ACCEPT</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>好啦，现在我们是把网桥 <code>br0</code> 上的数据原封不动的直接通过宿主机的网卡转发出去，但是别忘了，我们的数据包中的源地址相对于宿主机所处的网络环境可是一个内网地址，所以我们还需要使用 <code>NAT</code> 技术做一个源地址转换，好在 <code>iptables</code> 已经提供了非常好用的功能为我们所用</p>
<h2>6 使用 iptables 为宿主机提供 NAT 功能</h2>
<p>先看看宿主机的 <code>iptables</code> 中已经配置的规则</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> iptables <span class="token parameter variable">-t</span> nat <span class="token parameter variable">-L</span> --line-numbers</span>
<span class="line">Chain PREROUTING <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"></span>
<span class="line">Chain INPUT <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"></span>
<span class="line">Chain OUTPUT <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"></span>
<span class="line">Chain POSTROUTING <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以看到我这里都是空的，所以我可以放心的去添加一条规则来做 <code>NAT</code> 了</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line">➜  ~ <span class="token function">sudo</span> iptables <span class="token parameter variable">-t</span> nat <span class="token parameter variable">-A</span> POSTROUTING <span class="token parameter variable">-s</span> <span class="token number">192.168</span>.166.0/24 <span class="token operator">!</span> <span class="token parameter variable">-o</span> br0 <span class="token parameter variable">-j</span> MASQUERADE</span>
<span class="line">➜  ~ <span class="token function">sudo</span> iptables <span class="token parameter variable">-t</span> nat <span class="token parameter variable">-L</span> --line-numbers</span>
<span class="line">Chain PREROUTING <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"></span>
<span class="line">Chain INPUT <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"></span>
<span class="line">Chain OUTPUT <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"></span>
<span class="line">Chain POSTROUTING <span class="token punctuation">(</span>policy ACCEPT<span class="token punctuation">)</span></span>
<span class="line">num  target     prot opt <span class="token builtin class-name">source</span>               destination         </span>
<span class="line"><span class="token number">1</span>    MASQUERADE  all  --  <span class="token number">192.168</span>.166.0/24     anywhere </span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>那么刚才我们用到的这条命令，大致意思就是说：把 linux 收到的属于 <code>192.168.166.0/24</code> 这个网段的数据包全都使用源地址转换的方式交给宿主机的物理网卡转发出去</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> iptables <span class="token parameter variable">-t</span> nat <span class="token parameter variable">-A</span> POSTROUTING <span class="token parameter variable">-s</span> <span class="token number">192.168</span>.166.0/24 <span class="token operator">!</span> <span class="token parameter variable">-o</span> br0 <span class="token parameter variable">-j</span> MASQUERADE</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>来让我们看看，现在我们的虚拟机与外部的网络环境是否打通了，我在虚拟机 <code>ubuntu</code> 上尝试了一下，真是太棒了，已经能够和我的计算机进行通信了！</p>
<p></p>
<h2>7 配置 DNS 服务器</h2>
<p>好啦，截止目前为止，只要我们的宿主机的网络是可以连接互联网的，那么虚拟机也是同样可以连同互联网的，不过我们尝试 <code>ping www.baidu.com</code> 会发现不行，那是因为我们还没有配置域名服务器，让我们配置一下</p>
<p>我们只需要编辑这个文件就可以了，但是这种方式只能是临时配置，重启之后就没有咯</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh"><pre><code class="language-bash"><span class="line"><span class="token function">sudo</span> <span class="token function">vim</span> /etc/resolv.conf</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p></p>
<p>再让我们试一下！哇塞，这次可以了！！！</p>
<p></p>


]]></content:encoded>
    </item>
  </channel>
</rss>