【LeetCode】128. 最長連續序列 結題報告 (C++)
阿新 • • 發佈:2018-11-11
原題地址:https://leetcode-cn.com/problems/longest-consecutive-sequence/description/
題目描述:
給定一個未排序的整數陣列,找出最長連續序列的長度。
要求演算法的時間複雜度為 O(n)。
示例:
輸入: [100, 4, 200, 1, 3, 2]
輸出: 4
解釋: 最長連續序列是 [1, 2, 3, 4]。它的長度為 4。
解題方案:
本題的型別是並查集,從來沒有做過的題型。。學習學習!
初始思路是對陣列進行排序,再查詢最大的連續序列。因為題目要求時間複雜度為O(N),這種方式不可用。
將連續的數字合併為一個數組,最後比較這些陣列,看哪個陣列中的元素最多。。
並查集還是很妙的,其中的相關資料:http://www.cnblogs.com/horizonice/p/3658176.html
百度百科含有列題以及C++程式碼:https://baike.baidu.com/item/並查集/9388442?fr=aladdin#6_2
並查集一般包含建立函式,查詢函式,合併函式。
本程式碼設計很精妙,使用了並查集模組,在模組裡直接定義了並查集的陣列,以及查詢函式和合並函式。
class Solution { //並查集模板(已優化) struct DisJointSet { vector<int> _id;//元素 vector<int> _size;//集合內的元素個數 int max_size;//最大集合的元素個數【額外需要用到的引數】 int _count;//集合總個數 DisJointSet(int Num) { for (int i = 0; i < Num; i++) { _id.emplace_back(i); _size.emplace_back(1); } _count = Num; max_size = 1; } //查詢 int find_(int p) { while (p != _id[p]) { _id[p] = _id[_id[p]]; p = _id[p]; } return p; } //合併 void _union(int p, int q) { int i = find_(p); int j = find_(q); if (i == j)return; if (_size[i] > _size[j]) { _id[j] = i; _size[i] += _size[j]; max_size = max(max_size, _size[i]); } else { _id[i] = j; _size[j] += _size[i]; max_size = max(max_size, _size[j]); } _count--; } }; public: int longestConsecutive(vector<int>& nums) { if (nums.size() == 0) return 0; DisJointSet disJointSet(nums.size()); unordered_set<int> nums_set; //記錄是否有查複數字 或者 是否已經有數字的前後的數 unordered_map<int, int> nums_disJointSetID_map; //<數字,ID> 與並查集ID一一對應,不需改動模板引數 for (int i = 0; i < nums.size(); i++) { if (nums_set.find(nums[i]) != nums_set.end()) continue; //存在重複數字 nums_set.insert(nums[i]); nums_disJointSetID_map[nums[i]] = i; if(nums_set.find(nums[i] - 1) != nums_set.end()) //是否有前一個數 { disJointSet._union(nums_disJointSetID_map[nums[i]], nums_disJointSetID_map[nums[i] - 1]); } if(nums_set.find(nums[i] + 1) != nums_set.end()) //是否有後一個數 { disJointSet._union(nums_disJointSetID_map[nums[i]], nums_disJointSetID_map[nums[i] + 1]); } } return disJointSet.max_size; } };