public class BingChaJi {
    
    public static int countIslands(int[][] m) {
        
        if (m == null || m[0] == null) {
            return 0;
        }
        
        int N = m.length;
        
        int M = m[0].length;
        int res = 0;
        
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                
                if (m[i][j] == 1) {
                    
                    res++;
                    infect(m, i, j, N, M);
                }
            }
        }
        return res;
    }
    private static void infect(int[][] m, int i, int j, int N, int M) {
        
        if (i < 0 || i >= N || j < 0 || j >= M || m[i][j] != 1) {
            return;
        }
        
        m[i][j] = 2;
        
        infect(m, i + 1, j, N, M);
        infect(m, i - 1, j, N, M);
        
        infect(m, i, j + 1, N, M);
        
        infect(m, i, j - 1, N, M);
    }
    
    public static class Element<V> {
        public V value;
        public Element(V value) {
            this.value = value;
        }
    }
    public static class UnionFindSet<V> {
        public HashMap<V, Element> elementMap;
        
        public HashMap<Element<V>, Element<V>> fatherMap;
        
        public HashMap<Element<V>, Integer> sizeMap;
        public UnionFindSet(List<V> list) {
            elementMap = new HashMap<>();
            fatherMap = new HashMap<>();
            sizeMap = new HashMap<>();
            for (V value : list) {
                Element<V> element = new Element<V>(value);
                elementMap.put(value, element);
                fatherMap.put(element, element);
                sizeMap.put(element, 1);
            }
        }
        
        private Element<V> findHead(Element<V> element) {
            Stack<Element<V>> path = new Stack<>();
            while (element != fatherMap.get(element)) {
                path.push(element);
                element = fatherMap.get(element);
            }
            while (!path.isEmpty()) {
                fatherMap.put(path.pop(), element);
            }
            return element;
        }
        public boolean isSameSet(V a, V b) {
            if (elementMap.containsKey(a) && elementMap.containsKey(b)) {
                return findHead(elementMap.get(a)) == findHead(elementMap.get(b));
            }
            return false;
        }
        public void union(V a, V b) {
            if (elementMap.containsKey(a) && elementMap.containsKey(b)) {
                Element<V> aF = findHead(elementMap.get(a));
                Element<V> bF = findHead(elementMap.get(b));
                if (aF != bF) {
                    Element<V> big = sizeMap.get(aF) >= sizeMap.get(bF) ? aF : bF;
                    Element<V> small = big == aF ? bF : aF;
                    fatherMap.put(small, big);
                    sizeMap.put(big, sizeMap.get(aF) + sizeMap.get(bF));
                    sizeMap.remove(small);
                }
            }
        }
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);
            list.add(5);
            list.add(6);
            UnionFindSet<Integer> set = new UnionFindSet(list);
            set.union(1, 2);
            boolean sameSet = set.isSameSet(1, 2);
            System.out.println(sameSet);
        }
    }
    public static void main(String[] args) {
        int[][] arr =
                {{0, 0, 0, 0, 0, 0, 0},
                        {0, 1, 1, 0, 0, 0, 0},
                        {0, 1, 0, 0, 0, 0, 0},
                        {0, 0, 0, 1, 1, 1, 1},
                        {0, 0, 0, 1, 0, 0, 1},
                        {0, 0, 0, 0, 0, 0, 0},
                        {0, 1, 1, 1, 0, 0, 0}};
        System.out.println("感染前数组的样子:");
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[0].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
        int i1 = countIslands(arr);
        System.out.println("岛的个数是:" + i1);
        System.out.println("感染后的数组的样子:");
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[0].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}