<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>个人博客</title><link>https://shiroe120.github.io/blog/</link><description>Recent content on 个人博客</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 15 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://shiroe120.github.io/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>两数之和</title><link>https://shiroe120.github.io/blog/posts/%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://shiroe120.github.io/blog/posts/%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C/</guid><description>&lt;h2 id="例题1"&gt;例题1&lt;/h2&gt;
&lt;p&gt;167.&lt;a href="https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/"&gt;两数之和&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="题面"&gt;题面&lt;/h3&gt;
&lt;p&gt;给你一个下标从 &lt;strong&gt;1&lt;/strong&gt; 开始的整数数组 &lt;code&gt;numbers&lt;/code&gt; ，该数组已按 &lt;strong&gt;非递减顺序排列&lt;/strong&gt; ，请你从数组中找出满足相加之和等于目标数 &lt;code&gt;target&lt;/code&gt; 的两个数。如果设这两个数分别是 &lt;code&gt;numbers[index1]&lt;/code&gt; 和 &lt;code&gt;numbers[index2]&lt;/code&gt; ，则 &lt;code&gt;1 &amp;lt;= index1 &amp;lt; index2 &amp;lt;= numbers.length&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;以长度为 2 的整数数组 &lt;code&gt;[index1, index2]&lt;/code&gt; 的形式返回这两个整数的下标 &lt;code&gt;index1&lt;/code&gt; 和 &lt;code&gt;index2&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;你可以假设每个输入 &lt;strong&gt;只对应唯一的答案&lt;/strong&gt; ，而且你 &lt;strong&gt;不可以&lt;/strong&gt; 重复使用相同的元素。&lt;/p&gt;
&lt;p&gt;你所设计的解决方案必须只使用常量级的额外空间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 1：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;输入：numbers = [2,7,11,15], target = 9
输出：[1,2]
解释：2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="思路"&gt;思路&lt;/h3&gt;
&lt;p&gt;利用数组的有序性，初始化左右两个指针，指向第一个数和最后一个数，如果两个指针所指之数的和大于target，左移右指针，反之右移左指针。（两指针所指之数的和大于target时，如果右指针不变，右移左指针，则两数之和只会变大，永远无法等于target）&lt;/p&gt;
&lt;h3 id="为什么这样做不会有遗漏"&gt;&lt;strong&gt;为什么这样做不会有遗漏？&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;我们可以把这看作是对于暴力的优化。&lt;strong&gt;正常来说，我们使用两个循环来遍历所有组合&lt;/strong&gt;。而这种情况下，我们可以视为，先用左指针从小到大遍历数组，当左指针指向某个数时，我们来关注右指针，右指针从大到小遍历，如果两数之和大于target，那说明当前的右指针所指之数太大，左移，直到两数之和等于target。接下来继续遍历左指针，我们右移左指针，这个时候可以注意到，左指针右移导致左指针所指之数变大，思考一下，&lt;strong&gt;那我们还需要从最大值开始遍历右指针吗？当然不需要了，我们完全可以从右指针正指着的位置开始遍历。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;于是，左指针不会回头，右指针不会回头，直到两者相遇，那么时间复杂度我们就优化到了O(n).&lt;/p&gt;
&lt;h2 id="例题2"&gt;例题2&lt;/h2&gt;
&lt;ol start="15"&gt;
&lt;li&gt;&lt;a href="https://leetcode.cn/problems/3sum/solution/shuang-zhi-zhen-xiang-bu-ming-bai-yi-ge-pno55/"&gt;三数之和&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;思路&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>关于我</title><link>https://shiroe120.github.io/blog/about/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://shiroe120.github.io/blog/about/</guid><description>&lt;p&gt;你好，我是 Shiroe，一个普通的开发者。&lt;/p&gt;
&lt;p&gt;&lt;img alt="装饰图片" loading="lazy" src="https://shiroe120.github.io/blog/saya.png"&gt;&lt;/p&gt;
&lt;h3 id="我的兴趣"&gt;我的兴趣&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;绘画&lt;/li&gt;
&lt;li&gt;摄影&lt;/li&gt;
&lt;li&gt;技术&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;梦想是成为艺术家&lt;/p&gt;
&lt;h3 id="联系方式"&gt;联系方式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/shiroe120"&gt;shiroe120&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Email: &lt;a href="mailto:120shirou@gmail.com"&gt;120shirou@gmail.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;感谢访问我的博客！&lt;/p&gt;</description></item><item><title/><link>https://shiroe120.github.io/blog/posts/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://shiroe120.github.io/blog/posts/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/</guid><description>&lt;h1 id="二分查找"&gt;二分查找&lt;/h1&gt;
&lt;p&gt;我们仍然从一个最基本的例题开始，随后讲解一下二分的扩展题型。&lt;/p&gt;
&lt;h2 id="例题"&gt;&lt;a href="https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/"&gt;例题&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;给你一个按照非递减顺序排列的整数数组 &lt;code&gt;nums&lt;/code&gt;，和一个目标值 &lt;code&gt;target&lt;/code&gt;。请你找出给定目标值在数组中的开始位置和结束位置。&lt;/p&gt;
&lt;p&gt;如果数组中不存在目标值 &lt;code&gt;target&lt;/code&gt;，返回 &lt;code&gt;[-1, -1]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;你必须设计并实现时间复杂度为 &lt;code&gt;O(log n)&lt;/code&gt; 的算法解决此问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例 1：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;输入：nums = [5,7,7,8,8,10], target = 8
输出：[3,4]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;示例 2：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;输入：nums = [5,7,7,8,8,10], target = 6
输出：[-1,-1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;示例 3：&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;输入：nums = [], target = 0
输出：[-1,-1]
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;p&gt;二分查找的基本思路有不少变种，我学习的是红蓝染色法，个人觉得这种方法是非常直观好理解的， 我最开始看的是b站灵茶山艾符的视频。&lt;/p&gt;
&lt;p&gt;过去我们了解的二分查找的基本思想可能是&lt;strong&gt;从一个有序数组中不断取中值与target比较，相同则返回，不同则分类讨论&lt;/strong&gt;。而在这里，我们把上述逻辑简化成了如果&lt;strong&gt;大于等于target，和小于target两种情况&lt;/strong&gt;，于是我们分类讨论这两种情况，&lt;strong&gt;最终返回第一个大于等于target的数。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;先简单说一下思路，左指针left指向最左边，右指针right指向最右边，如果中值小于target，说明需要左移left，反之亦然，下面是代码：&lt;/p&gt;
&lt;p&gt;首先这里是&lt;strong&gt;闭区间&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-kotlin" data-lang="kotlin"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lower&lt;/span&gt;_bound(nums: IntArray, target: Int): Int{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 我们最终返回第一个大于等于target的数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; left = &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; right = nums.size - &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 显然，如果是闭区间的话，左右一开始指向的都是需要遍历（检查）的数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (left &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; right) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 我们思考一下，left和right处于什么状态时，说明所有数都已经被遍历，由于是闭区间，left &amp;gt; right 时，已完全遍历，while里反着写
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;val&lt;/span&gt; mid = left + (right - left) / &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (nums[mid] &amp;lt; target) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; left = mid + &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 由于是闭区间，这里实际的范围是[left, ... , right]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 关于为什么这里要+1，如果 left = mid ，则数组实际上是[mid, ... , right]，而mid已经是小于target了，target如果存在于这个数组，则一定在[mid + 1, ... , right]中
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; right = mid - &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; left
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;开区间&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>