LeetCode刷題筆記 01 Two Sum

2021-02-19 馬志峰的編程筆記

怎麼樣,學習完前3章之後有沒有按捺不住?是不是已經不滿足於做課後練習了呢?

恰好今天是周末,時間比較寬裕,我們來刷一道leetcode

連結

https://leetcode.com/problems/two-sum/

題目

給定一個整型數組和另外一個整數,在數組找出兩個整數,使得它們的和等於給定的整數。返回這兩個整數的下標。
假設總能找到這樣的兩個數,且結果唯一

示例

給定 nums = [ 2, 7, 11, 15 ], target = 9,
因為 nums[ 0 ] + nums[ 1 ] = 2 + 7 = 9,
return [ 0, 1 ].

弄懂了題目的意思之後我們就正式開始解題了。

這裡建議大家先自己嘗試一下。

第一回合

可能最容易想到的一個方法就是通過兩個循環來解決這個問題

外層循環從0開始遍歷:[ 02, 07, 11 ]

內層循環從1開始遍歷:[ 07, 11, 15 ]

如果對應位置上的整數相加等於給定的值,則返回下標

我們把頁面往下拖動,在下拉框裡面選擇」c++」,就可以開始擼代碼了。

建議大家先去寫寫看,多想幾種解題方法出來。

想到之後在網站上就可以直接編碼了,不需要藉助IDE。

我是這麼寫的:

class Solution {  public:      vector<int> twoSum(vector<int>& nums, int target) {          vector<int> vecResult;          for( int i = 0; i < nums.size() - 1; ++i )          {              for( int j = i + 1; j < nums.size(); ++j )              {                  if( nums[i] + nums[j] == target )                  {                      vecResult.push_back( i );                      vecResult.push_back( j );                      return vecResult;                  }              }          }          return vecResult;      }  };

點擊 「Run Code」,哦也,一次通過!
點擊 「Submit Solution」,OK, Accepted!
點擊 「Detail」 看一看,天啊擼,什麼鬼。耗時809ms!擊敗了5.6%的用戶!
這他媽的跟360提示開機速度擊敗了全國1%的用戶一樣埋汰人啊!!!

仔細研究研究:
nums.size()調用了太多次,如果先調用一次把結果存起來呢?
OK,

第二回合

點擊 「Edit Code」,修改代碼

class Solution {  public:      vector<int> twoSum(vector<int>& nums, int target) {          vector<int> vecResult;          auto iSize = nums.size();          for( int i = 0; i < iSize - 1; ++i )          {              for( int j = i + 1; j < iSize; ++j )              {                  if( nums[i] + nums[j] == target )                  {                      vecResult.push_back( i );                      vecResult.push_back( j );                      return vecResult;                  }              }          }          return vecResult;      }  };

提交之後再來看一下詳情,我擦,486ms了!擊敗了33.49%的用戶!!!
提升了20多個百分點啊,查看一下被接受的提交總數是273183,這乘下來一下子前進了五萬多名。自信心激增,有木有!!!

再一看,iSize - 1也調用了好多次,同樣的問題嘛。好,也把它給提前存下來試試看。

class Solution {  public:      vector<int> twoSum(vector<int>& nums, int target) {          vector<int> vecResult;          auto iSize = nums.size();          auto iOutterSize = iSize - 1;          for( int i = 0; i < iOutterSize; ++i )          {              for( int j = i + 1; j < iSize; ++j )              {                  if( nums[i] + nums[j] == target )                  {                      vecResult.push_back( i );                      vecResult.push_back( j );                      return vecResult;                  }              }          }          return vecResult;      }  };

提交,shit,496ms!怎麼還耗時增加了? 難道定義一個臨時量這麼影響性能結果?

到底是怎麼回事,各路大神能告訴我嗎?

想了半天沒想能,先把問題記錄下來。咱們繼續。

書上說可以用列表初始化的方式來初始化數組,咱們把返回值的地方改一改,看看能不能有所提升

ok

第三回合

class Solution {  public:      vector<int> twoSum(vector<int>& nums, int target) {          auto iSize = nums.size();          for( int i = 0; i < iSize - 1; ++i )          {              for( int j = i + 1; j < iSize; ++j )              {                  if( nums[i] + nums[j] == target )                  {                      return { i, j };                  }              }          }          vector<int> vecResult;          return vecResult;      }  };

499ms?這個統計沒問題吧?

不過書上也說了,建議創建空的vector,然後動態添加元素。看來動態添加的效率果然要高一些

我們把 return { i, j } 改成創建一個臨時量再返回試試

vector<int> temp = { i, j };  return temp;

652ms,果然創建一個臨時量挺佔用時間的

當然這些都是我們粗淺的解釋,在沒有接觸到更多知識之前不妨把這些記下來,留著以後探索。

想想還有什麼可以改的???

序列中的元素有三種訪問方式

我們只用了下標,範圍for不容易用到這來,不如我們先試試迭代器?

第四回合

class Solution {  public:      vector<int> twoSum(vector<int>& nums, int target) {          vector<int> vecResult;          int i = 0;          for( auto itr = nums.begin(); itr != nums.end() - 1; ++itr)          {              int j = i + 1;              for( auto itrInner = itr + 1; itrInner != nums.end(); ++itrInner )              {                  if( (*itr) + (*itrInner) == target )                  {                      vecResult.push_back( i );                      vecResult.push_back( j );                      return vecResult;                  }                  ++j;              }              ++i;          }          return vecResult;      }  };

在寫代碼的時候我們就應該知道迭代器在這種查找下標的場合不太適用。

我們不得不定義兩個變量i和j來記錄下標

事實也正是這樣,當我們submit代碼的時候被拒絕了,原因是在大的數據集面前消耗了過長的時間。

好吧,目前看來我們會的也就這麼多了。

真的是這樣嗎?還有沒有其他方法沒想到?再仔細看看筆記?

大家有沒有嘗試過把入參修改一下呢?

vector<int> twoSum(const vector<int> &nums, const int &target)

有沒有不需要兩個循環就能解決的辦法呢?

如果自己實在想不出來,可以去討論區看看別人的解法

https://discuss.leetcode.com/category/9/two-sum

如果大家其他的解法歡迎隨時和我討論,也可以加入學習群一起交流(公眾號底部菜單)。

相關焦點

  • LeetCode-1.兩數之和(Two Sum)
    相信每個想刷leetcode的人,第一次打開網站,就從這道題開始的。一起起航吧,Great Voyage.
  • LeetCode001 - TwoSum
    關於刷題有兩點吧:之前也刷過題,但是都是刷一下就中斷了,沒有堅持下來,導致自己也沒有什麼總結和沉澱
  • LeetCode刷題第三周【數組(簡單)】
    日期Oct.28 - Nov.03 2020(每日一題)Ps:本周我們接著上一周繼續刷數組,難度依舊是簡單,題目不再按順序,而是隨機挑選,下周開始會加深難度。隨著學校的開課,我會將平時上課的內容和筆記也整理成MK的格式上傳。
  • leetcode刷題指南之PatchingArray
    掃描數組, 令sum表示當前我們能得到1 ~ sum的值。那麼接下來的數x如果小於等於sum+1, 那麼我們直接加進來更新sum的值(sum += x), 否則, 我們為了得到sum+1這個數, 我們必然要加入一個數。顯然加入sum+1這個數是最優決策。例子:以nums = [1,2,7], n = 14為例。
  • 六十四、開始刷Leetcode之旅(Python版本)
    這個是中文的網址:https://leetcode-cn.com/problemset/all/下圖就是我的國際版本,其實我主要在國際版混日子,刷了100多題,其實我很菜的。這是它的官網,https://leetcode.com。
  • Leetcode每日一題(python)1.Two Sum
    今天的題目是leetcode的第一題。1.
  • 笨方法刷 leetcode(一)
    )本篇記錄5道題的解題思路,可能都是最笨的方法示例 2:輸入: s = "abc"輸出: true限制:0 <= len(s) <= 100原題連結:https://leetcode-cn.com/problems/is-unique-lcci/解決思路:
  • LeetCode刷題筆記(1)
    一個人的命運啊,不僅要考慮歷史的進程,還要考慮個人的努力,近期明顯懈怠下來的筆者決定開啟LeetCode刷題大業,從第一題開始按順序刷掉LeetCode
  • LeetCode-18.四數之和(4Sum)
    滿足要求的四元組集合為:[ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2]]來源:力扣(LeetCode)連結:https://leetcode-cn.com/problems/4sum/Link:https://leetcode.com/problems/4sum/雙指針O(N^
  • LeetCode-0001.TwoSum
    數據結構和算法是每個程式設計師必須要掌握的知識,LeetCode 平臺上的算法題種類和數量也足夠多。從今天開始,我會按分類進行刷題,鍛鍊一下自己的腦袋,並且以圖文並茂的形式把筆記寫下來。首先從簡單的數組專題開始,所有代碼以及測試用例都會上傳到 github上,歡迎查閱:https://github.com/CPythoner/LeetCode。1.
  • LeetCode 例題精講 | 04 用雙指針解 Two Sum:縮減搜索空間
    這就是本題的雙指針解法了。讓我們先看看答案是怎麼寫的:public int[] twoSum(int[] nums, int target) { int i = 0; int j = nums.length - 1; while (i < j) { int sum = nums[i] + nums
  • 字節大佬Leetcode刷題筆記,看完吊打問你算法的面試官
    介紹leetcode 題解,記錄自己的 leetcode 解題之路。目前分為五個部分:第一個部分是 leetcode 經典題目的解析,包括思路,關鍵點和具體的代碼實現。第二部分是對於數據結構與算法的總結第三部分是 anki 卡片, 將 leetcode 題目按照一定的方式記錄在 anki 中,方便大家記憶。
  • LeetCode-75.顏色分類(Sort Colors)
    此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。注意:不能使用代碼庫中的排序函數來解決這道題。來源:力扣(LeetCode)連結:https://leetcode-cn.com/problems/sort-colorsLink:https://leetcode.com/problems/sort-colors簡單計數O(N)把[0,1,2]數量分別記下來,最後填充起來
  • ​LeetCode刷題實戰15題: 三數之和
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做三數之和 ,我們先來看題面:https://leetcode.com/problems/3sum/描述給定一個整數的數組,要求尋找當中所有的a,b,c三個數的組合,使得三個數的和為0.注意,即使數組當中的數有重複,同一個數也只能使用一次。
  • LeetCode Top 100 高頻算法題 15. 3Sum
    LeetCode Top 100高頻算法題,即LeetCode上最高頻的100道求職面試算法題。
  • LeetCode 每日一題(順帶吹水聊聊未來)
    2020-7-20 00:35:07寫完小冊,看到每日一題刷新了,【簡單】難度,那就順帶刷了,再順帶和小夥伴們吹吹水吧~題目 給定一個已按照升序排列 的有序數組,找到兩個數使得它們相加之和等於目標數。來源:力扣(LeetCode)連結:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted著作權歸領扣網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
  • leetcode刷題最強指南(版本1.0)
    為什麼會有這篇刷題指南很多剛開始刷題的同學都有一個困惑:面對leetcode上近兩千道題目,從何刷起
  • 小張刷題計劃
    原題為了提高自己的代碼能力,小張制定了 LeetCode 刷題計劃,他選中了 LeetCode 題庫中的 n 道題,編號從 0 到 n-1,並計劃在 m 天內按照題目編號順序刷完所有的題目(注意,小張不能用多天完成同一題)。在小張刷題計劃中,小張需要用 time[i] 的時間完成編號 i 的題目。
  • leetcode刷對了麼
    通過做這些題能讓你對這些最基礎的算法的思路有非常紮實的了解和訓練。 2、編程題。比如:atoi,strstr,add two num,括號匹配,字符串乘法,通配符匹配,文件路徑簡化,Text Justification,反轉單詞等等,這些題的Edge Case,Corner Case有很多。
  • 春節大禮包|刷題技巧+80道Leetcode
    為了跳槽,我前兩年的春節都是在刷題中度過的,目前為止刷了小四百道leetcode,也算是有一些經驗,今天就跟大家分享下學習方法和我總結的乾貨。後來發現了 Leetbook[1] 這個寶藏,才算是找到了適合自己的刷題方法。