Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example,
Given [100, 4, 200, 1, 3, 2]
,
The longest consecutive elements sequence is [1, 2, 3, 4]
. Return its length: 4
.
Your algorithm should run in O(n) complexity.
O(n)。突破关键是去找上下是否有出现过。sequence就是可以随便取,这题还不要求顺序,那就是真真随便取。完全set概念了有出现即可。
法1:HashSet(更优更好写)。
1.先把所有元素都放到set里。
2.遍历number,取出一个元素,用up和down分别count和它连续的数的个数,每次找到+1-1的数计数好后就把它们在set中remove掉。然后把这个up和down夹出来的个数打个擂台。
细节:
1.一开始遍历统计的set和后来用来避免重复查同一元素的visited set可以直接共用一个。只要visit以后把set里的这个元素删掉即可。
2.不用同时维护length+up指针+down指针,最后可以直接用up, down指针的位置得到length的。
法2.UnionFind + HashMap<value, index>。
用fathers[]当基础数据结构,count[]记录每个集合内的个数, map帮忙记录某个值在哪个index方便后续的union。 遍历number,如果发现上下元素有出现过,那就把它们合到一起。要记得在union的时候,把count合并一下,合并count后打擂台。
我的实现1:
class Solution { public int longestConsecutive(int[] nums) { Set<Integer> set = new HashSet<>(); for (int i : nums) { set.add(i); } Set<Integer> visited = new HashSet<>(); int ans = 0; for (int i : set) { if (visited.contains(i)) { continue; } int len = 1; int offset = 1; while (set.contains(i + offset)) { visited.add(i + offset); len++; offset++; } offset = -1; while (set.contains(i + offset)) { visited.add(i + offset); len++; offset--; } ans = Math.max(ans, len); } return ans; } }
实现1 九章优雅版
public class Solution { /** * @param nums: A list of integers * @return an integer */ public int longestConsecutive(int[] num) { // write you code here Set<Integer> set = new HashSet<>(); for (int item : num) { set.add(item); } int ans = 0; for (int item : num) { if (set.contains(item)) { set.remove(item); int l = item - 1; int r = item + 1; while (set.contains(l)) { set.remove(l); l--; } while (set.contains(r)) { set.remove(r); r++; } ans = Math.max(ans, r - l - 1); } } return ans; } }
实现2:
class Solution { private int maxL = 1; public int longestConsecutive(int[] nums) { if (nums == null || nums.length == 0 ) { return 0; } int[] fathers = new int[nums.length]; int[] count = new int[nums.length]; Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { fathers[i] = i; count[i] = 1; } for (int i = 0; i < nums.length; i++) { if (map.containsKey(nums[i])) { continue; } if (map.containsKey(nums[i] - 1)) { union(fathers, count, i, map.get(nums[i] - 1)); } if (map.containsKey(nums[i] + 1)) { union(fathers, count, i, map.get(nums[i] + 1)); } map.put(nums[i], i); } return maxL; } private int find(int[] fathers, int x) { if (fathers[x] == x) { return x; } return fathers[x] = find(fathers, fathers[x]); } private boolean union(int[] fathers, int[] count, int x, int y) { int fatherX = find(fathers, x); int fatherY = find(fathers, y); if (fatherX != fatherY) { fathers[fatherY] = fatherX; count[fatherX] += count[fatherY]; maxL = Math.max(maxL, count[fatherX]); } return fatherX != fatherY; } }