Javascript 交换顺序联合查找
所以我在做面试练习题时遇到了这样一个问题: 给定一个字符串str和一组指示字符串中哪些索引可以交换的对,返回执行允许的交换所产生的按字典顺序排列的最大字符串。您可以多次交换索引 范例 对于str=“abdc”和pairs=[[1,4],[3,4]],输出应为 swapLexOrder(str,pairs)=“dbca” 通过交换给定的索引,可以得到字符串:“cbda”、“cbad”、“dbac”、“dbca”。此列表中按字典顺序排列的最大字符串是“dbca” 我有一个关于寻找工会的有效答案,但我的答案太慢了:Javascript 交换顺序联合查找,javascript,union-find,lexicographic-ordering,Javascript,Union Find,Lexicographic Ordering,所以我在做面试练习题时遇到了这样一个问题: 给定一个字符串str和一组指示字符串中哪些索引可以交换的对,返回执行允许的交换所产生的按字典顺序排列的最大字符串。您可以多次交换索引 范例 对于str=“abdc”和pairs=[[1,4],[3,4]],输出应为 swapLexOrder(str,pairs)=“dbca” 通过交换给定的索引,可以得到字符串:“cbda”、“cbad”、“dbac”、“dbca”。此列表中按字典顺序排列的最大字符串是“dbca” 我有一个关于寻找工会的有效答案,但我
[time limit] 4000ms (js)
0 ≤ pairs.length ≤ 5000,
pairs[i].length = 2.
1 ≤ str.length ≤ 10^4
有人能帮我调整代码以提高速度吗?
以下是我的代码:
function swapLexOrder(str, pairs) {
if (!pairs.length){
return str
}
answerHash = {}
unmoved = findUnmoved(pairs, str.length)
unionsArr = findUnions(pairs)
for (i in unmoved){
answerHash[unmoved[i]] = str[(unmoved[i]-1)]
}
unionsArr.forEach(function(union){
letters = []
for (i in union){
letters.push(str[(union[i]-1)])
}
letters.sort()
union.sort(function(a,b){
return b-a
})
for (j in union){
answerHash[union[j]] = letters[j]
}
})
string = []
for (keys in answerHash){
string.push(answerHash[keys])
}
return string.join('')
}
//if two pairs share a number they belong in the same array
findUnions = function(pairs, unions){
if (!unions){
unions = [pairs[0]];
pairs.shift();
}else{
if(pairs.length){
unions.push(pairs[0])
pairs.shift()
}
}
if (!pairs.length){
return unions
}
unite = true
while (unite && pairs.length){
unite = false
loop1:
for (i in unions){
loop2:
for (j in pairs){
if (unions[i].includes(pairs[j][0])){
unions[i].push(pairs[j][1])
pairs.splice(j, 1)
unite = true
break loop1
}else if (unions[i].includes(pairs[j][1])){
unions[i].push(pairs[j][0])
pairs.splice(j, 1)
unite = true
break loop1
}
}
}
}
return findUnions(pairs, unions)
}
findUnmoved = function(pairs, length){
range = []
for (var i=1;i<length+1;i++){
range.push(i);
}
allNum = [].concat.apply([], pairs)
range = range.filter(function(x){
return (!allNum.includes(x))
})
return range
}
函数顺序(str,pairs){
如果(!pairs.length){
返回str
}
answerHash={}
unmoved=findUnmoved(成对,str.length)
unionsArr=findUnions(对)
为了(我无动于衷){
answerHash[unmoved[i]]=str[(unmoved[i]-1)]
}
unionsArr.forEach(功能(union){
字母=[]
为了(我在联盟中){
字母推送(str[(union[i]-1)])
}
letters.sort()
union.sort(函数(a,b){
返回b-a
})
代表(联合法官){
答案hash[union[j]]=字母[j]
}
})
字符串=[]
for(answerHash中的键){
string.push(应答哈希[键])
}
返回字符串。join(“”)
}
//如果两对共享一个数字,则它们属于同一数组
findUnions=函数(对、并集){
如果(!联合){
联合=[对[0]];
pairs.shift();
}否则{
if(成对长度){
UNION.push(对[0])
pairs.shift()
}
}
如果(!pairs.length){
回归工会
}
统一=正确
while(unite&&pairs.length){
联合=假
循环1:
(i)在工会中{
循环2:
用于(j成对){
if(并[i].包括(对[j][0])){
并[i].推(对[j][1])
线对.拼接(j,1)
统一=正确
打破循环1
}else if(并[i].包括(对[j][1])){
并集[i].推送(对[j][0])
线对.拼接(j,1)
统一=正确
打破循环1
}
}
}
}
返回findUnions(成对、联合)
}
findUnmoved=函数(对,长度){
范围=[]
对于(var i=1;i而言,这一方法工作得更快
function swapLexOrder(str, pairs) {
//Turn pairs into edge lists: O(n+m)
var graph = new Array(str.length).fill(0).map(e=>[]);
for(var pair of pairs) {
graph[pair[0]-1].push(pair[1]-1);
graph[pair[1]-1].push(pair[0]-1);
}
//Build all the ccs with dfs: O(n+m)
var ccs = [], ccnum = 0;
for(var c in str) {
if(ccs[c])
continue;
ccs[c] = ++ccnum;
var dfs = [...graph[c]];
while(dfs.length) {
var d = dfs.shift();
if(ccs[d])
continue;
ccs[d] = ccnum;
dfs.push(...graph[d]);
}
}
//Group words by ccs: O(n)
var ccWords = new Array(ccnum).fill(0).map(e=>[]);
for(var c in str) {
ccWords[ccs[c]-1].push(str[c]);
}
//Sort all words: O(n log n)
ccWords.map(e=>e.sort());
//Build the new string: O(n)
var output = "";
for(var c in str) {output += ccWords[ccs[c]-1].pop(); }
return output;
}