數據結構算法 - LeetCode 刷題

數據結構和算法的課程講解,目前已告一段落,也算是完成了自己的一個心願。因爲去年聽某同學抱怨過,說自己去愛奇藝面試,其他問題都答得不錯,面試官問了一個哈夫曼算法的題沒答出來,後來面試官很明確的說,我們還是想找一個會些算法基礎的。

如果之前有學過數據結構和算法,建議大家不定時的去刷刷算法題,因爲從面試的角度來講,目前 BAT 和 TMD 等一線互聯網企業或多或少都會有幾個算法題,而對應屆畢業生來說算法的要求度則更高。當然大家面試過程中遇到的算法題,90%都來自於各大刷題網站。另一方面從開發的角度來講,數據結構和算法絕對是一門內功,思維方式和嚴謹程度上都會有一個跳躍性的提升。就在前幾天團隊出現了兩個疑難雜症,一個是小米手機的 View 數據丟失的 Bug,一個是直播間高斯模糊算法的卡頓。解決問題時若我們能站在底層源碼和算法的角度去分析問題,絕對會要輕鬆許多。

在線編程評測的平臺有很多,比較有名的有 Hihocoder,LintCode,LeetCode。我們一般在 LeetCode 上刷題比較多,目前有九百多道題目。不必每道題都刷,但建議至少把前 200 道刷一遍。不要看標籤,不要看標籤,標籤相當於問題的分類,看了標籤就會往那個方向去想,不利於自主思考。如果目前正處於面試階段建議每天刷兩三題,如果目前是工作狀態可以不定時的刷一刷。LeetCode 的題型都非常簡單明瞭,並不需要複雜的理解,一般都在幾十行以內就可以解決了,如果你寫了上百行代碼,就肯定說明你想太多了或太複雜,雖然都能用很短的代碼就能解決,但並不意味着 LeetCode 的題目非常簡單,實際上LeetCode 基本上涉及到了所有常規的算法類型。

獨立解決一個問題是最好的學習途徑。如果你被某一個地方卡住了,不要急着去網上找答案,不管代碼寫得有多麼爛先想辦法實現,然後再想想有沒有更好的方案,最後再去參考參考他人的實現方式。切記不是爲了簡單的實現,而是去想有沒有更好的解決方案。請看第一題:

1. Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

  Given nums = [2, 7, 11, 15], target = 9,
  Because nums[0] + nums[1] = 2 + 7 = 9,

  return [0, 1].

這道題從通過率來看已經比較高了,題目本身也非常簡單,用暴力破解即可:

  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){
          return new int[]{i,j};
        }
      }
    }
    return null;
  }

單從結果上來看是通過了,但切記不是爲了簡單的實現,而是去想有沒有更好的解決方案。就好比現在有一個棘手的問題擺在咋們面前,我們的追求只是簡單去實現,還是應該想想有沒有更好的解決方案呢?再想想:

  public int[] twoSum(int[] nums, int target) {
    Map<Integer,Integer> maps = new HashMap<>(nums.length);
    for(int i=0;i<nums.length;i++){
      int diff = target - nums[i];
      if(maps.containsKey(diff)){
        return new int[]{maps.get(diff),i};
      }
      maps.put(nums[i],i);
    }
    return null;
  }

從上面來看,該題算法的複雜度可以優化到 O(n) ,那爲何測試結果卻顯示未達最優?我們之前分析 HashMap 的源碼時,可知其查找算法的複雜度,最好的情況是 O(1) 最壞是 O(logN) 。因此我們還可以有更好的解決方案:

  public int[] twoSum(int[] nums, int target) {
    Integer[] filter = new Integer[4096];
    int length = nums.length;
    int diff = 0;
    for(int i=0;i<length;i++){
      diff = target - nums[i];
      Integer index = filter[diff&4095];
      if(index != null){
        return new int[]{index,i};
      }
      filter[nums[i]&4095] = i;
    }
    return null;
  }


8. String to Integer (atoi)

Implement atoi which converts a string to an integer.

The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned.

Note:

  • Only the space character ’ ’ is considered as whitespace character.
  • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.

這題也是鵝廠面試題中的一道高頻算法題,題目本身並不難,但從通過率上來看卻是一道極低的題目,主要考察的是我們思考問題的時候是否嚴謹。好比我們在公司完成了一個需求,測試沒問題,灰度也沒問題,但上線就出現問題了。某部分原因也是我們在做需求的時候很多場景沒有考慮到,在公司老大最喜歡說的口頭禪之一就是 “你這樣寫有坑”。

  int myAtoi(string str) {
    long result = 0;
    int len = str.length();
    int index = 0;
    // 過濾空格
    while(index<len && str[index] == ' '){ 
      index++;
    }
        
    // 正負符號
    int negative = 1;     
    if(index<len && str[index] == '+'){
      index++;
    }
    else if(index<len && str[index] == '-'){
      negative = -1;
      index++;
    }
        
    if(index == len){
      return 0;
    }
        
    // 計算結果
    while(index<len){
      char c = str[index++];
            
      if(c<'0' || c>'9'){
        break;
      }
            
      result = result*10 + (c-'0');
      // 處理越界的情況
      if(negative*result > INT_MAX)
        return INT_MAX;
      else if(negative*result < INT_MIN)
        return INT_MIN;
    }  
    return result*negative;
  }

視頻鏈接:https://pan.baidu.com/s/1onpWrPBrS3cvnMmc9FzJhQ
視頻密碼:txq8

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章