哈希&雙指針問題-LeetCode 128、18(哈希set查詢,二分查找)

  • 2019 年 10 月 7 日
  • 筆記

作者:TeddyZhang,公眾號:算法工程師之路

DFS基礎問題:LeetCode #128 #18

1

編程題

【LeetCode #128】最長連續序列 給定一個未排序的整數數組,找出最長連續序列的長度。

要求算法的時間複雜度為 O(n)。

示例:

輸入: [100, 4, 200, 1, 3, 2] 輸出: 4 解釋: 最長連續序列是 [1, 2, 3, 4]。它的長度為 4。

解題思路: 首先使用一個哈希set將我們的數據全都保存,然後遍歷整個數組,假如遍歷到了數字A,其一定在哈希set中,這是毋庸置疑的。接着我們需要進入一個while循環去判斷A+1,A+2,A+3…是不是也在這個哈希表中,如果嘗試到數字B,其不在哈希表中則退出,此時最長連續序列B-A。

既然我們查找過了A+1,A+2,A+3, 其在哈希表中,那麼我們遍曆數組的時候要需要遍歷這些值么?顯然不需要,因此我們可以優化一下,什麼時候才需要進入上述過程!

當某一個數的前一個數沒有在數組,也就是沒有在哈希set中,我們就從這個數字開始遍歷,統計到的連續序列一定是該部分最長的!!!

C++代碼:

class Solution {  public:      int longestConsecutive(vector<int>& nums) {          if(nums.size() == )  return ;          unordered_set<int> mySet(nums.begin(), nums.end());          int res = ;            for(auto num: nums){              if(mySet.count(num - ) == ){                  int tmp = num;  //保存初始數據                  while(mySet.count(tmp)){                      tmp++;                  }                   res = max(res, tmp-num);              }          }          return res;      }  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/longest-consecutive-sequence

【LeetCode #18】四數之和

給定一個包含 n 個整數的數組 nums 和一個目標值 target,判斷 nums 中是否存在四個元素 a,b,c 和 d ,使得 a + b + c + d 的值與 target 相等?找出所有滿足條件且不重複的四元組。

注意:答案中不可以包含重複的四元組。

示例:

給定數組 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

滿足要求的四元組集合為: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

著作權歸領扣網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解題思路: 四數之和的大體思路是:首先固定兩個數,然後將思路之和的問題變成兩數之和,使用雙指針的方法去尋找,由於對於兩數之和,使用雙指針的前提數組是一個排序數組,因此我們先對該數組進行排序,然後根據上述的思路再去遍歷。

注意在遍歷時候的幾種剪枝方法:

  • 如果nums[i]>target && target>0,說明後面的nums[i]肯定不存在我們想要的值,因為後面的值都大於target.
  • 固定的兩個元素不能是相同元素,如果是相同的元素,那麼經過兩數求和算法後勢必會存在重複的四元組,因此我們需要判斷j > i+1 && nums[j][j-1], 如果為真,兩數之和算法不會運行!
  • 兩數求和怎麼去重的就不解釋了,遇到重複的,讓指針跳過就好了!
  • 如果不想這麼麻煩,可以使用DFS方法中的set去重

C++代碼

class Solution {  public:      vector<vector<int>> fourSum(vector<int>& nums, int target) {          if(nums.size()<) return {};          sort(nums.begin(),nums.end());          vector<vector<int>> res;          for(int i=;i<nums.size()-3;i++)          {              if(nums[i]>target&&target>) break;              if(i> && nums[i]==nums[i-1])                  continue;    // 去重              for(int j=i+;j<nums.size()-2;j++)              {                  if(j>i+ && nums[j]==nums[j-1])                      continue;  // 去重                  int l=j+;                  int r=nums.size()-1;                  while(l<r)                  {                      if(nums[i]+nums[j]+nums[l]+nums[r]<target)                          while(l<r && nums[l]==nums[++l]);  // 去重                      else if(nums[i]+nums[j]+nums[l]+nums[r]>target)                          while(l<r && nums[r]==nums[--r]);                      else                      {                          vector<int> temp{nums[i],nums[j],nums[l],nums[r]};                          res.push_back(temp);                          while(l<r && nums[l]==nums[++l]);                          while(l<r && nums[r]==nums[--r]);                      }                  }              }          }          return res;      }  };  

附一個自己寫的DFS超時代碼,哈哈哈,關鍵不是DFS,這個不難,主要是去重比較複雜,我這裡使用的是set去重,不管怎麼樣,都會超時。。。

class Solution {  public:      set<vector<int>> res;      vector<vector<int>> res_;      vector<int> tmp;      vector<vector<int>> fourSum(vector<int>& nums, int target) {          if (nums.empty())  return res_;            dfs(res, nums, target, );          for(auto i: res){              res_.push_back(i);          }          return res_;      }        void dfs(set<vector<int>>& res, vector<int>& nums, int target, int start){          if (tmp.size() > ){              return;          }          if(tmp.size() == ){              vector<int> t;              for(auto i: tmp){                  t.push_back(i);              }   // set數組對於不同順序的相同元素認定為不同元素,無法去重,因此先排序              sort(t.begin(), t.end());              if(target ==   && res.count(t) == ){                  res.insert(t);              }              return;          }          for(int i = start; i < nums.size(); i++){              if(i != start && nums[i] == nums[i-1]){                  continue;              }              tmp.push_back(nums[i]);              dfs(res, nums, target-nums[i], i+);              tmp.pop_back();          }      }  };

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/4sum