0

所以我在做面试练习题,我遇到了这个问题:给定一个字符串 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
}

它可能是我用来查找工会的功能,但我在想也许我可以在不创建哈希的情况下做到这一点?此外,如果你知道解决问题的更好方法,我总是愿意学习一些新的东西。谢谢!

4

1 回答 1

0

这个工作得更快。

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;
}
于 2017-09-26T02:13:25.927 回答