文字列sと、文字列内のいくつかの「インデックスペア」配列ペアを指定します。ここで、pairs [i] = [a、b]は、文字列内の2つのインデックスを表します(番号は0から始まります)。
インデックスの任意のペアの文字を、ペアで何度でも交換できます。
sが数回の交換後になり得る最小の文字列を辞書式に返します。
例1:
入力:s = "dcab"、ペア= [[0,3]、[1,2]]
出力: "bacd"
説明:
交換s [0]およびs [3]、s = "bcad"
交換s [1 ]およびs [2]、s = "bacd"
例2:
入力:s = "dcab"、ペア= [[0,3]、[1,2]、[0,2]]
出力: "abcd"
説明:
s [0]とs [3]を交換します。s = " 「bcad」は
s [0]とs [2]を
交換し、s = "acbd"はs [1]とs [2]を交換します。s = "abcd"
例3:
入力:s = "cba"、ペア= [[0,1]、[1,2]]
出力: "abc"
説明:
s [0]とs [1]を
交換します。s= "bca"はs [1を交換します。 ]およびs [2]、s = "bac"
交換s [0]およびs [1]、s = "abc"
促す:
1 <= s.length <= 10 ^ 5
0 <= pairs.length <= 10 ^ 5
0 <= pair [i] [0]、pairs [i] [1] <s.lengths
には小文字の英語のみが含まれます
出典:LeetCode
リンク:https ://leetcode-cn.com/problems/smallest-string-with-swaps
著作権はLeetCodeが所有しています。商用の再版については、公式の承認に連絡してください。非商用の再版については、出典を示してください。
アイデア:私は無駄です。この質問は書きませんでした。もともと文字列操作を実行したかったのですが、10分ほど考えたときに、文字列を書くことができても複雑すぎるため、文字列を無効にしました。後でこの質問は大丈夫だと思いました。コレクションの使用と確認は、前回コピーしたテンプレートを配置するようなものですが、挿入しないと、emmmmはまだ良すぎます。
ps:誰かがコメントエリアにコメントを投稿した場合、私はそれを直接コピーしました
class Solution {
public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
//初始化连通图
DisjointSetUnion dsu = new DisjointSetUnion(s.length());
for(List<Integer> pair:pairs){
//合并
dsu.unionSet(pair.get(0),pair.get(1));
}
//使用map存储祖先节点到子节点列表的映射,存储并查集结果
//例如s = "dcab", pairs = [[0,3],[1,2]]
//0:[d,b] 1:[c,a]
Map<Integer,List<Character>> map =new HashMap<Integer,List<Character>>();
for(int i =0;i<s.length();i++){
int parent = dsu.find(i);//找到该节点的父节点
if(!map.containsKey(parent)){
map.put(parent,new ArrayList<Character>());
}
map.get(parent).add(s.charAt(i));
}
//对map中的值进行排序
for(Map.Entry<Integer,List<Character>> entry:map.entrySet()){
Collections.sort(entry.getValue(),new Comparator<Character>(){
public int compare(Character c1,Character c2){
return c2-c1;
}
});
}
StringBuffer sb = new StringBuffer();
for(int i =0;i<s.length();i++){
int x = dsu.find(i);
List<Character> list =map.get(x);
sb.append(list.remove(list.size()-1));
}
return sb.toString();
}
}
//定义并差集类
class DisjointSetUnion{
int n; //并查集长度
int[] rank; //节点等级
int[] f; //存储对应的祖先节点
//构造函数,初始化属性
public DisjointSetUnion(int n){
this.n = n;
rank = new int[n];
Arrays.fill(rank,1);
f = new int[n];
for(int i=0;i<n;i++){
f[i] = i;
}
}
//方法find,寻找给节点的祖先
public int find(int x){
return f[x] == x?x:(f[x]=find(f[x]));
}
//合并到一个图中,共同有一个祖先
public void unionSet(int x, int y) {
int fx=find(x),fy = find(y);
if(fx==fy){
return;
}
if(rank[fx]<rank[fy]){
//swap(fx,fy);
int temp = fx;
fx=fy;
fy=temp;
}
//fx级别高,要作为祖先
rank[fx] +=rank[fy];
f[fy] = fx;
}
}