[Java] Dijkstra, Time: O(N * logN)
\nclass Solution {\n    public int minimumDistance(String s) {\n        final int N = (s == null) ? 0 : s.length();\n        if (N <= 2) {\n            return 0
```\nclass Solution {\n    public int minimumDistance(String s) {\n        final int N = (s == null) ? 0 : s.length();\n        if (N <= 2) {\n            return 0;\n        }\n\n        PriorityQueue<Node> minHeap = new PriorityQueue<>();\n        Set<Node> visited = new HashSet<>();\n\n        minHeap.offer(new Node(-1, 0, 0));\n\n        while (!minHeap.isEmpty()) {\n            Node curr = minHeap.poll();\n\n            if (curr.currCharIdx == N - 1) {\n                return curr.steps;\n            }\n\n            visited.add(curr);\n\n            // use the same finger\n            int nextCharIdx = curr.currCharIdx + 1;\n            int dist = getDist(s, curr.currCharIdx, nextCharIdx);\n            Node next = new Node(curr.prevCharIdx, nextCharIdx, curr.steps + dist);\n            if (!visited.contains(next)) {\n                minHeap.offer(next);\n            }\n\n            // use another finger\n            dist = 0;\n            if (curr.prevCharIdx >= 0) {\n                dist = getDist(s, curr.prevCharIdx, nextCharIdx);\n            }\n            next = new Node(curr.currCharIdx, nextCharIdx, curr.steps + dist);\n            if (!visited.contains(next)) {\n                minHeap.offer(next);\n            }\n        }\n\n        return -1;\n    }\n\n    private int getDist(String s, int idx1, int idx2) {\n        int[] coord1 = getCoord(s.charAt(idx1));\n        int[] coord2 = getCoord(s.charAt(idx2));\n        return Math.abs(coord1[0] - coord2[0]) + Math.abs(coord1[1] - coord2[1]);\n    }\n\n    private int[] getCoord(char ch) {\n        int idx = ch - \'A\';\n        return new int[] { idx / 6, idx % 6 };\n    }\n\n    static class Node implements Comparable<Node> {\n        final int prevCharIdx;\n        final int currCharIdx;\n        final int steps;\n\n        Node(int prevCharIdx, int currCharIdx, int steps) {\n            this.prevCharIdx = prevCharIdx;\n            this.currCharIdx = currCharIdx;\n            this.steps = steps;\n        }\n\n        @Override\n        public int compareTo(Node that) {\n            return Integer.compare(this.steps, that.steps);\n        }\n\n        @Override\n        public int hashCode() {\n            return currCharIdx * 31 + prevCharIdx;\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj) {\n                return true;\n            }\n\n            if (!(obj instanceof Node)) {\n                return false;\n            }\n\n            Node that = (Node) obj;\n            return this.prevCharIdx == that.prevCharIdx\n                && this.currCharIdx == that.currCharIdx;\n        }\n    }\n}\n```
[]