leetcode-longest-consecutive-sequence

题目大意

  https://leetcode.com/problems/flatten-binary-tree-to-linked-list/

  给你一个无序的数组,找出其中的一个序列(不要求按照原数组的顺序),序列满足连续(类似1,2,3,4,5…..),问序列的最大长度。要求时间复杂度是O(n)

题目分析

  这道题可以利用并查集做,遍历数组,将每个数n和n-1归为一组,最后对出现次数进行统计计算。但是并查集每次操作的复杂度是Ackerman函数的反函数,此反函数在算法复杂度分析时,可以近似视为常数,所以总复杂度O(n)。

  还有一种简单的思路,思路参考这里:https://discuss.leetcode.com/topic/6148/my-really-simple-java-o-n-solution-acceptedmap.get(i)含义就是以中间包含i元素的最大的序列长度,那么每次在数组中遇到一个数字n,就获取map.get(n-1)map.get(n+1),根据这这两个值更新n处的值,但也要更新n-leftn+right值。

代码

  并查集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class Solution {
private Map<Integer, Integer> parent;
private Map<Integer, Integer> rank;
private int[] nums;
private void init() {
for (int n : nums) {
parent.put(n - 1, n - 1);
parent.put(n, n);
rank.put(n - 1, 0);
rank.put(n, 0);
}
}
private int find(int x) {
if (parent.get(x) == x) {
return x;
} else {
int tmp = find(parent.get(x));
parent.put(x, tmp);
return tmp;
}
}
private void unit(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return;
}
if (rank.get(x) < rank.get(y)) {
parent.put(x, y);
} else {
parent.put(y, x);
if (rank.get(x) == rank.get(y)) {
int tmp = rank.get(x);
rank.put(x, tmp + 1);
}
}
}
private boolean same(int x, int y) {
return find(x) == find(y);
}
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
parent = new HashMap<Integer, Integer>();
rank = new HashMap<Integer, Integer>();
this.nums = nums;
init();
for (int n : nums) {
unit(n, n - 1);
}
Map<Integer, Integer> freq = new HashMap<Integer, Integer>();
Set<Integer> keySet = parent.keySet();
for (Integer k : keySet) {
int f = find(k);
if (freq.containsKey(f)) {
int count = freq.get(f);
freq.put(f, count + 1);
} else {
freq.put(f, 1);
}
}
Set<Integer> keySet2 = freq.keySet();
int maxV = Integer.MIN_VALUE;
for (Integer k : keySet2) {
int v = freq.get(k);
maxV = Math.max(v, maxV);
}
return maxV - 1;
}
}

  第二种简单方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Solution {
public int longestConsecutive(int[] nums) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int ans = 0;
for (int n : nums) {
if (!map.containsKey(n)) { // 避免重复更新
int left = 0;
if (map.containsKey(n - 1)) {
left = map.get(n - 1);
}
int right = 0;
if (map.containsKey(n + 1)) {
right = map.get(n + 1);
}
int sum = left + right + 1;
map.put(n, sum); // 注意n处值也要更新
ans = Math.max(ans, sum);
map.put(n - left, sum);
map.put(n + right, sum);
}
}
return ans;
}
}

  时间复杂度:O(n)