String swapLexOrder(String str, int[][] pairs) { Map<Integer, Set<Integer>> map = new HashMap<Integer, Set<Integer>>(); for (int[] edge: pairs) { int u = edge[0]; int v = edge[1]; map.putIfAbsent(u, new HashSet<Integer>()); map.putIfAbsent(v, new HashSet<Integer>()); map.get(u).add(v); map.get(v).add(u); } // DFS and collect all connected components, order ascending List<TreeSet<Integer>> ccs = new ArrayList<TreeSet<Integer>>(); Set<Integer> visited = new HashSet<Integer>(); for (Integer u: map.keySet()) { if (!visited.contains(u)) { visited.add(u); TreeSet<Integer> current = new TreeSet<Integer>(); current.add(u); dfs(map, u, visited, current); ccs.add(current); } } char[] ans = str.toCharArray(); // Collect chars at connected component, sort des and populate output for (TreeSet<Integer> set : ccs) { List<Character> ordered = new ArrayList<Character>(); Iterator iter = set.iterator(); while (iter.hasNext()) { int index = (int)iter.next() - 1; ordered.add(str.charAt(index)); } Collections.sort(ordered, Collections.reverseOrder()); iter = set.iterator(); int i = 0; while (iter.hasNext()) { ans[(int)iter.next() - 1] = ordered.get(i++); } } return new String(ans); } void dfs(Map<Integer, Set<Integer>> map, int u, Set<Integer> visited, TreeSet<Integer> current) { for (int v: map.get(u)) { if (!visited.contains(v)) { visited.add(v); current.add(v); dfs(map, v, visited, current); } } }