string - 查找具有重复字母的单词(排列)的排名

标签 string algorithm permutation

虽然关于这个问题的帖子已经很多了,但我还是要发布这个。我不想发布作为答案,因为它不起作用。这篇文章的答案 ( Finding the rank of the Given string in list of all possible permutations with Duplicates ) 对我不起作用。

所以我尝试了这个(这是我抄袭的代码的汇编以及我试图处理重复的代码)。非重复案例工作正常。 BOOKKEEPER 生成 83863,而不是所需的 10743。

(阶乘函数和字母计数器数组“repeats”工作正常。我没有发布以节省空间。)

while (pointer != length)
{
    if (sortedWordChars[pointer] != wordArray[pointer])
    {
        // Swap the current character with the one after that
        char temp = sortedWordChars[pointer];
        sortedWordChars[pointer] = sortedWordChars[next];
        sortedWordChars[next] = temp;
        next++;

        //For each position check how many characters left have duplicates, 
        //and use the logic that if you need to permute n things and if 'a' things 
        //are similar the number of permutations is n!/a!


        int ct = repeats[(sortedWordChars[pointer]-64)];
        // Increment the rank
        if (ct>1) { //repeats?
            System.out.println("repeating " + (sortedWordChars[pointer]-64));
            //In case of repetition of any character use: (n-1)!/(times)!
            //e.g. if there is 1 character which is repeating twice,
            //x* (n-1)!/2!                      
                int dividend = getFactorialIter(length - pointer - 1);
                int divisor = getFactorialIter(ct);
                int quo = dividend/divisor;
                rank += quo;
        } else {
            rank += getFactorialIter(length - pointer - 1);                 
        }                       
    } else
    {
        pointer++;
        next = pointer + 1;
    }
}

最佳答案

注意:此答案适用于基于 1 的排名,如示例中隐含指定的那样。下面是一些至少适用于提供的两个示例的 Python。关键事实是 suffixperms * ctr[y]//ctr[x] 是首字母为 y 的排列数 - (i + 1) perm 的后缀。

from collections import Counter

def rankperm(perm):
    rank = 1
    suffixperms = 1
    ctr = Counter()
    for i in range(len(perm)):
        x = perm[((len(perm) - 1) - i)]
        ctr[x] += 1
        for y in ctr:
            if (y < x):
                rank += ((suffixperms * ctr[y]) // ctr[x])
        suffixperms = ((suffixperms * (i + 1)) // ctr[x])
    return rank
print(rankperm('QUESTION'))
print(rankperm('BOOKKEEPER'))

Java 版本:

public static long rankPerm(String perm) {
    long rank = 1;
    long suffixPermCount = 1;
    java.util.Map<Character, Integer> charCounts =
        new java.util.HashMap<Character, Integer>();
    for (int i = perm.length() - 1; i > -1; i--) {
        char x = perm.charAt(i);
        int xCount = charCounts.containsKey(x) ? charCounts.get(x) + 1 : 1;
        charCounts.put(x, xCount);
        for (java.util.Map.Entry<Character, Integer> e : charCounts.entrySet()) {
            if (e.getKey() < x) {
                rank += suffixPermCount * e.getValue() / xCount;
            }
        }
        suffixPermCount *= perm.length() - i;
        suffixPermCount /= xCount;
    }
    return rank;
}

未排序排列:

from collections import Counter

def unrankperm(letters, rank):
    ctr = Counter()
    permcount = 1
    for i in range(len(letters)):
        x = letters[i]
        ctr[x] += 1
        permcount = (permcount * (i + 1)) // ctr[x]
    # ctr is the histogram of letters
    # permcount is the number of distinct perms of letters
    perm = []
    for i in range(len(letters)):
        for x in sorted(ctr.keys()):
            # suffixcount is the number of distinct perms that begin with x
            suffixcount = permcount * ctr[x] // (len(letters) - i)
            if rank <= suffixcount:
                perm.append(x)
                permcount = suffixcount
                ctr[x] -= 1
                if ctr[x] == 0:
                    del ctr[x]
                break
            rank -= suffixcount
    return ''.join(perm)

关于string - 查找具有重复字母的单词(排列)的排名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22642151/

相关文章:

java - 使用 Stringbuilder 创建 long[] 数组

c - 循环持续时间比预期检查空行的时间长

ios - Swift 中的字符串解释

python - for循环中的自定义排序

python - 生成字符串代码错误的排列

python - 字符串中重复的字符

algorithm - 使用什么样的算法来生成方阵?

java - 我执行 "Intersection of Two Linked Lists"的错误在哪里?

algorithm - Verhoeff 算法的正确排列循环

MySQL 单个列表的排列