public static void findWay(int[][] maze, Pair start, Pair end) {
        // Min Heap holding
        PriorityQueue<Pw> heap = new PriorityQueue<>(maze.length * maze.length , new Comparator<Pw>() {
            @Override
            public int compare(Pw o1, Pw o2) {
                return Integer.compare(o1.weight, o2.weight);
            }
        });

        Map<Pair, Pair> parent = new HashMap<>();
        Map<Pair, Integer> cost = new HashMap<>();

        heap.add(new Pw(start, 0));
        parent.put(start, null);
        cost.put(start, 0);

        while(!heap.isEmpty()) {
            Pw pairWeight = heap.remove();
             // early exit condition
            if(pairWeight.p.equals(end)){
                break;
            }

            for(Pair neighbour : getAllNeighbour(pairWeight.p, maze)) {
                int newCost = cost.get(pairWeight.p) + neighbour.weight;
                if(!parent.containsKey(neighbour) && (!cost.containsKey(neighbour) || newCost < cost.get(neighbour))) {
                   cost.put(neighbour, newCost);
                    // adding heuristic - which is Math.abs(end.x - neighbour.x) + Math.abs(end.y - neighbour.y)  distance from end Goal
                   int weight = newCost + Math.abs(end.x - neighbour.x) + Math.abs(end.y - neighbour.y);
                   heap.add(new Pw(neighbour,weight));
                   parent.put(neighbour, pairWeight.p);
                }
            }

        }

        //iterate on rev pointer and keep adding them to the maze
        if(parent.containsKey(end)) {
            maze[end.x][end.y] = 2;
            while(true) {
                if(parent.get(end) == null) {
                    break;
                }
                // mark the maze with the path
                maze[parent.get(end).x][parent.get(end).y] = 2;
                end = parent.get(end);
            }
        }
        printBoard(maze);


    }