1. 程式人生 > >流下了不學無術的淚水——今天你刷題了嗎(一)

流下了不學無術的淚水——今天你刷題了嗎(一)

點選上方“程式人生”,選擇“置頂公眾號”

第一時間關注程式猿(媛)身邊的故事

工作以後,你有多久沒有做演算法題了,反正班克我是工作一年了,然後一年沒做演算法題了。

640?wx_fmt=gif&wxfrom=5&wx_lazy=1

但是班克我是一個積極向上、熱愛學習的程式設計師啊!作為一個標杆一般的人物,怎麼能停止學習的腳步呢!!!

640?wx_fmt=gif&wxfrom=5&wx_lazy=1

本來帥氣的班克童鞋是準備一個人關起房門來偷偷學習的。然鵝,沒有本來,你以為小班克和那些自私的小婊砸一樣嗎?不,我們不一樣!!

所以今天小班克來到了這裡,想必任何在座的各位牛逼的程式設計師,一定都知道LeetCode這個網站,但我還是得和某些不知道的同學普及下知識。LeetCode是一款線上刷題的網站,在LeetCode上有很多程式相關的面試題,如果每一道題都能做出來,對大家面試大公司會很有幫助,如果你已經進入了大公司,那對你程式思維的鍛鍊也很有幫助。總之,就是對我們很有幫助!

以後小班克會在每一期的結尾,公佈一道LeetCode上面的題目,嫌小班克公佈慢的也可以自己登陸LeetCode網站自行刷題。然後在下一期的時候,小班克會給出題目的解題過程。小班克給出的解題過程僅是自己的解題過程,如果有什麼不對的地方,歡迎大家來指正交流(撕逼)~

640?wx_fmt=gif

今天第一期,正好LeetCode第一道題目比較簡單,我相信在座的各位大佬應該不用浪費時間做這道題,我就直接給出答案了。

題目如下:

640?wx_fmt=png

翻譯過來就是:給你一個整型陣列,需要你返回兩個數,這兩個數相加等於一個指定的數。

你必須保證每一個輸入的陣列都有且只有一個確定的解。

解題過程:

解題思路如下:使用最笨的方法(小班克演算法比較薄弱,暫時只能想到這個蠢方法),用兩個迴圈巢狀,將這個陣列中所有的組合都測試一遍,直到最後得到正確的答案為止。程式碼比較簡單,就不作過多的解釋了,直接貼出班克的程式碼:

public class Solution 
{
   public int[] TwoSum(int[] nums, int target)
   
{
       for(int i = 0; i < nums.Length; i++)
       {
           for(int j = i + 1; j < nums.Length; j ++)
           {
               if(nums[i] + nums[j] == target)
               {
                   int[] returnValue = new
int[2]{i, j};
                   return returnValue;
               }
           }
       }
         return null;
   }
}

時間複雜度:O(n^2)。這個應該不用解釋了吧= =

空間複雜度:O(1)。

什麼是空間複雜度呢?鑑於可能很多小朋友都忘了這些基礎知識(其實是小班克我忘了)。讓我們來看看百度的解答:

640?wx_fmt=png

看完之後我的表情如下圖(強調一下,小班克沒有他黑):

小班克我在仔(bai)細(du)思(yi)考(xia)之後,做出瞭如下的解釋:它是對一個演算法在執行過程中臨時佔用儲存空間大小的量度。所以它強調的是使用的輔助空間的的大小,而不是指所有的資料所佔用的空間。我覺得簡單來解釋,就是所要建立的臨時變數的個數。我們這裡就建立了一個臨時變數(int[] returnValue),所以是O(1)。下面我再舉一個O(N)的例子,我們看如下程式碼。

640?wx_fmt=png

很明顯,這是斐波那契數列,針對這種遞迴的演算法,我們可以看出來每一次遞迴都會建立一個ptr,這個函式一共執行n-1次,因此開闢了n-1個臨時變數,去掉常量,所以這個函式的時間複雜度為O(n),這回大家應該明白了吧。

那麼我們再回到這個問題,這個問題除了我這種笨笨的解決方案還有沒有其他高大上的解決方案呢?那當然是有的啦!

官方還給出了另外兩種解決方案。

附加方案一:

public int[] twoSum(int[] nums, int target) {
   Map<Integer, Integer> map = new HashMap<>();
   for (int i = 0; i < nums.length; i++) {
       map.put(nums[i], i);
   }
   for (int i = 0; i < nums.length; i++) {
       int complement = target - nums[i];
       if (map.containsKey(complement) && map.get(complement) != i) {
           return new int[] { i, map.get(complement) };
       }
   }
throw new IllegalArgumentException("No two sum solution");}

解題思路:這個方案通過增加臨時空間複雜度的方式,來降低時間複雜度,先將陣列存入雜湊表中,然後用雜湊表代替了原來的For迴圈的查詢方式,將查詢的時間複雜度由O(n)降低到了O(1)。別問我為什麼雜湊表的查詢的時間複雜度是O(1),不知道的請自行百度。

時間複雜度:O(n)。

空間複雜度:O(n)。從演算法中我們可以看到開闢了n臨時空間。

附加方案二:

public int[] twoSum(int[] nums, int target) {
   Map<Integer, Integer> map = new HashMap<>();
   for (int i = 0; i < nums.length; i++) {
       int complement = target - nums[i];
       if (map.containsKey(complement)) {
           return new int[] { map.get(complement), i };
       }
       map.put(nums[i], i);
   }
   throw new IllegalArgumentException("No two sum solution");}

解題思路:這個解題方案和上一個很向,差別在於,他沒有一開始就將陣列中所有的數都存入雜湊表中,而是通過遍歷陣列,將陣列中不滿足條件的整數按照遍歷順序依次存入雜湊表中。具體過程如下圖:

640?wx_fmt=png

第一輪檢查,發現雜湊表中沒有數和2相加等於9,所以將2存入雜湊表中。

第二輪檢查,得出答案。

時間複雜度:O(n)。

空間複雜度:O(n)。從程式中,我們可以看出最多建立n個臨時空間。

沒想到第一題這麼簡單的一道題,就寫了這麼多,想來可能是小班克我有點囉嗦了(也有可能是我太菜了哈哈~)。

下期題目:

那我們接下來就來看看下一期的題目:

640?wx_fmt=png

翻譯過來就是:給出兩個表示非負整數的數字連結串列,數字以相反的順序儲存,每個連結串列都儲存該非負整數某一位上的數字。計算兩個非負整數的和,並以連結串列的方式返回。簡單做個比喻:342,以連結串列的儲存形式就是,2->4->3。

各位大佬加油吧!期待各位大佬的表現喲~

640?wx_fmt=gif

- THE END -

本文作者:羅班克

作者介紹:工作一年經驗的Unity 程式設計師,主要從事遊戲開發。

如果你有好的原創文章想與大家分享,歡迎投稿。

徵稿要求:

①稿件字數以800~1500字左右為宜,多於2000字的文章在手機上閱讀起來比較麻煩,少於800字的文章看起來不過癮;

②你有自己拍的適合做文章插圖的照片也可一併附上~如果不方便,程式和小七也會幫你配圖~

640?wx_fmt=gif

加程式人生編輯們的微信,備註#投稿#:

程式 微信ID:druidlost  

小七 微信ID:duoshangshuang

點選圖片get往期內容

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=gif