import java.util.*;
public class Solution {
/**
* max increasing subsequence
* @param arr int整型一维数组 the array
* @return int整型
*/
public int MLS (int[] arr) {
// disjoint set
DisjointSet dSet = new DisjointSet(arr);
for (Integer node : dSet.nodes) {
dSet.union(node, node - 1); // 不断地寻找有无连续的节点
}
return dSet.maxSize;
}
}
class DisjointSet {
HashSet<Integer> nodes = new HashSet<>(); // 记录所有的节点
HashMap<Integer, Integer> parent = new HashMap<>(); // 记录所有节点的直接父节点
HashMap<Integer, Integer> size = new HashMap<>(); // 记录所有以某个节点为根的树的大小
int maxSize = 1;
public DisjointSet(int[] arr) {
// 按照并查集的特性,一开始所有节点的父节点指针都指向自己(这里使用HashMap来模拟两个节点之间的指向关系)
for (int i = 0; i < arr.length; i++) {
parent.put(arr[i], arr[i]);
size.put(arr[i], 1); // 初始大小为1
nodes.add(arr[i]);
}
}
public void union(int node1, int node2) {
if (!nodes.contains(node2)) { // 有了这一步让我想了想 还不如直接用现成的集合做,因为这一步导致并没有快多少,这个代码主要写来理解一下并查集这个数据结构吧
return;
}
int root1 = find(node1); //寻找父节点
int root2 = find(node2);
//合并两个树,大树的根作为小树根的父节点以实现合并
if (size.get(root1) > size.get(root2)) {
parent.put(root2, root1);
size.put(root1, size.get(root1) + size.get(root2));
maxSize = Math.max(maxSize, size.get(root1));
} else {
parent.put(root1, root2);
size.put(root2, size.get(root1) + size.get(root2));
maxSize = Math.max(maxSize, size.get(root2));
}
}
// 寻找树的根节点
public int find(int node) {
while(parent.get(node) != node) {
int temp = parent.get(node);
node = temp;
}
return node;
}
}