Algorithm design and analysis and search set

Posted by eagle1771 on Sun, 30 Jan 2022 20:44:02 +0100

Joint search set

summary

  • Function: support the rapid merging and searching of collections, with time complexity of O (1)
  • Two basic methods: isSameSet: whether two sets belong to the same set; union: merge two sets
  • The traditional data structure can not support the rapidity of the two methods at the same time. For example, the linked list structure can support fast consolidation, but it cannot support fast search; Hash table: supports fast lookup, but cannot support fast merge

Solution

(1) At the beginning, the pointer of each node points to itself
(2) If it points to Union (1, 3): the operation of merging the sets of 1 and 3 will point the pointer of 3 to 1. At this time, 1 is the vertex

(3) If multiple sets are merged, the vertex with less nodes should point to the vertex with more nodes. For example, union(1,2) is to change the pointer of 2

(4) isSameSet: the method can determine whether the top nodes are the same. For example, in the above figure: the return value of isSameSet(2, 6) is false; If in the following figure: the return value of isSameSet(2, 6) is true.

(5) Optimization problem (path compression): if the chain is too long, the time complexity will increase when using isSameSet. Using findHead method, the parent node of each node will eventually become the highest vertex in the process

After using findHead, connect 1 and 2 directly to the vertex

realization

    public static class Element<V>{
        //Packaging of samples to form elements
        //Internal use Element
        //External use V, use of generic classes
        public V value;

        public Element(V value){
         this.value = value;
        }
    }

    public static class UnionFindSet<V>{
        //Joint search set
        public HashMap<V, Element<V>> elementMap;
        //key is the sample, and value is the packaged element corresponding to the sample, which is convenient to judge whether the sample exists
        public HashMap<Element<V>, Element<V>> fatherMap;
        //key is the element and value is the parent element of the element
        public HashMap<Element<V>, Integer> sizeMap;
        //key is the vertex element of a set (representing the set), and value is the size of the set

        public UnionFindSet(List<V> list){
            //Initialization: requires the user to provide a collection
            elementMap = new HashMap<>();
            fatherMap = new HashMap<>();
            sizeMap = new HashMap<>();
            for (V value : list){
                //Traversal set
                //They all start as a set
                Element<V> element = new Element<>(value);
                elementMap.put(value, element);
                fatherMap.put(element, element);
                sizeMap.put(element, 1);
            }
        }

        private Element<V> findHead(Element<V> element){
            //A vertex element of a collection was found
            //And all the parent nodes of the node and its upper nodes are changed into vertex nodes
            Stack<Element<V>> stack = new Stack<>();
            while (element != fatherMap.get(element)){
                //Traverse to vertex element
                stack.push(element);
                element = fatherMap.get(element);
            }
            while (!stack.isEmpty()){
                //Modify this node and the parent node of the node above it to all vertex nodes
                fatherMap.put(stack.pop(), element);
            }
            return element;
        }

        public boolean isSameSet(V a, V b){
            //Judge whether a and b belong to the same set
            if (elementMap.containsKey(a) && elementMap.containsKey(b)){
                //a. b all exist in the set, and judge whether the vertex elements are the same
                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)){
                //If it does not exist in the set
                return;
            }
            if (isSameSet(a, b)){
                //Belong to the same set
                return;
            }
            //a. Top element of b
            Element<V> aH = findHead(elementMap.get(a));
            Element<V> bH = findHead(elementMap.get(b));
            //a. Distinction between larger sets and smaller sets in b
            Element<V> big = sizeMap.get(aH) >= sizeMap.get(bH) ? aH : bH;
            Element<V> small = big == aH ? bH : aH;
            //Connect smaller vertices to larger vertices
            fatherMap.put(small, big);
            sizeMap.put(big, sizeMap.get(small) + sizeMap.get(big));
            sizeMap.remove(small);
        }
    }

Title: Island problem

thinking

Ergodic matrix turns all connected 1 into 2. There are several islands in the process of turning 2 several times

    public static int countIslands(int[][] land){
        if (land == null || land[0] == null){
            return 0;
        }
        int x = land.length;
        int y = land[1].length;
        int res = 0;
        for (int i = 0; i < x; i++){
            for (int j = 0; j < y; j++){
                if (land[i][j] == 1){
                    //ergodic matrix 
                    res++;
                    infect(land, i, j, x, y);
                }
            }
        }
        return res;
    }

    public static void infect(int[][] land, int i, int j, int x, int y){
        //Change all connected as 1 into 2
        if (i < 0 || i >= x || j < 0 || j >= y || land[i][j] != 1){
            //End condition
            return;
        }
        land[i][j] = 2;
        //Traverse around
        infect(land, i + 1, j, x, y);
        infect(land, i - 1, j, x, y);
        infect(land, i, j + 1, x, y);
        infect(land, i, j - 1, x, y);
    }

    public static void main(String[] args) {
        int[][] land = {{0, 0, 1, 0, 1, 0},
                        {1, 1, 1, 0, 1, 0},
                        {1, 0, 0, 1, 0, 0},
                        {0, 0, 0, 0, 0, 0}};
        System.out.println(countIslands(land));
    }
  • Result demonstration:
  • Time complexity: O (X * Y) x: height of matrix, Y: width of matrix

Advanced: application of joint search set

(1) If the graph is particularly large, divide the graph, and the divided graph can process data in the subgraph at the same time to achieve the effect of parallelism
(2) However, the division map may increase the number of islands
(3) The boundary needs to be processed, and the points to which the boundary becomes in the same connection process are taken as a set
(4) Judge the connected points of the divided subgraph through the line. If the points of the subgraph have adjacent attributes, check whether they belong to a set. If not, the two sets are merged, and the number of graphs is reduced by one

Topics: Java Algorithm Union Find