鸠羽芊叶 發表於 2025-5-15 09:17:00

【LeetCode Hot 100】两数之和

<h1 id="两数之和">两数之和</h1>
<p>题目链接:LeetCode 两数之和</p>
<h2 id="题目描述">题目描述</h2>
<p>给定一个整数数组 <code>nums</code> 和一个整数目标值 <code>target</code>,请你在该数组中找出 和为目标值 <code>target</code>的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。</p>
<p><strong>示例1:</strong></p>
<pre><code>输入:nums = , target = 9
输出:
解释:因为 nums + nums == 9 ,返回 。
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:nums = , target = 6
输出:
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:nums = , target = 6
输出:
</code></pre>
<p>进阶要求:将时间复杂度从<span class="math inline">\(\mathcal{O}(n^2)\)</span>降低到<span class="math inline">\(\mathcal{O}(n)\)</span>。</p>
<h2 id="解题思路与代码">解题思路与代码</h2>
<p>题目给出了一个一维数组和一个目标值, 想要从数组中找到两个不相同的和为这个目标值的数字,设数组为<br>
<span class="math inline">\(A = \{a_0,a_1,\cdots,a_{n-1}\}\)</span> ,目标值为 <span class="math inline">\(b\)</span>,从数组$$A$$ 中找到两个值 <span class="math inline">\(a_i , a_j\)</span>,满足以下条件:</p>
<p></p><div class="math display">\[b = a_i + a_j ,\;\;\; 0\leq i\neq j\leq n-1.
\]</div><p></p><p>能想到,分配两个指针 <span class="math inline">\(i\)</span> 和 <span class="math inline">\(j\)</span> 在数组 <span class="math inline">\(A\)</span> 中分别遍历,每走一步即检查是否与 <span class="math inline">\(b\)</span> 相等且要避免指向相同位置,时间复杂度为 <span class="math inline">\(\mathcal{O}(n^2)\)</span>。</p>
<pre><code class="language-cpp">class Solution {
public:
    vector&lt;int&gt; twoSum(vector&lt;int&gt;&amp; nums, int target) {
      for (int i = 0 ; i &lt; nums.size() ; i++) {
            for (int j = 0 ; i != j &amp;&amp; j &lt; nums.size() ; j++) {
                if ( nums + nums == target)
                  return {i,j};      
                else
                  continue;
            }
      }
      return {};
    }
};
</code></pre>
<p>我们可以从另一个角度来考虑。因为 <span class="math inline">\(b\)</span> 是定值,分配一个指针 <span class="math inline">\(i\)</span> 遍历数组 <span class="math inline">\(A\)</span>,那么数组 <span class="math inline">\(A\)</span>被分为了两个部分(已经遍历过的部分和未遍历的部分),当指针 <span class="math inline">\(i\)</span>每指向一个未遍历部分的数时,都查看已经遍历过的部分是否有 <span class="math inline">\(a_j =b-a_i\)</span> ,能这样做的原因得益于题目说明 <span class="math inline">\(a_i \neq a_j\)</span>。<br>
如何查找一段序列 <span class="math inline">\(\{a_0,a_1,\cdots,a_{i-1}\}\)</span> 是否包含某值且要做到时间复杂度低,可以考虑哈希表,哈希表在查找键值的时间复杂度为 <span class="math inline">\(\mathcal{O}(1)\)</span>,算法时间复杂度将为 <span class="math inline">\(\mathcal{O}(n)\)</span>。</p>
<pre><code class="language-cpp">class Solution {
public:
    vector&lt;int&gt; twoSum(vector&lt;int&gt;&amp; nums, int target) {
      unordered_map&lt;int,int&gt; mp;
      for (int i = 0 ; i &lt; nums.size() ; i++)
      {
            auto it = mp.find(nums);
            if ( it != mp.end())
                return {it-&gt;second , i};
            mp] = i;
      }
      return {-1,-1};
    }
};
</code></pre>
<h2 id="扩展">扩展</h2>
<p>在上面两段代码实现中,都可以看到在返回值时直接返回一个包含数据的花括号(解法1:第7、12行 ; 解法2:第12行)。<br>
函数的返回类型 <code>vector&lt;int&gt;</code>可以按初始化列表初始化容器,得益于<code>vector</code>提供了一个接受初始化列表的构造函数,其签名如下:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
std::vector&lt;T&gt;::vector(std::initializer_list&lt;T&gt; init);
</code></pre>
<p>这个构造函数接受一个 <code>std::initializer_list&lt;T&gt;</code> 类型的参数,其中 <code>T</code> 是 <code>std::vector</code> 的元素类型。<code>std::initializer_list</code> 是一个轻量级的容器,它提供了一种方便的方式来表示初始化列表。</p><br><br>
来源:https://www.cnblogs.com/vvital/p/18877128
頁: [1]
查看完整版本: 【LeetCode Hot 100】两数之和