当前位置: 首页 > 知识库问答 >
问题:

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

李敏学
2023-03-14

我在这里发布这篇文章,尽管关于这个问题已经发布了很多。我不想发布答案,因为它不起作用。这篇文章的答案(在所有可能的重复排列列表中查找给定字符串的排名)对我来说不起作用。

所以我尝试了这个(这是我剽窃的代码的汇编,也是我处理重复的尝试)。不重复的案例工作正常。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;
    }
}

共有3个答案

干永丰
2023-03-14

我会说大卫·波斯特(被接受的答案)超级酷。然而,我想进一步提高它的速度。内部循环试图找到逆序对,并且对于每一个这样的逆序,它试图促进秩的增加。如果我们在该位置使用有序映射结构(二进制搜索树或BST),我们可以简单地从第一个节点(左下角)开始按顺序遍历,直到它到达BST中的当前字符,而不是遍历整个映射(BST)。在C语言中,std::map是BST实现的完美工具。下面的代码减少了循环中必要的迭代次数,并删除了if检查。

long long rankofword(string s)
{
    long long rank = 1;
    long long suffixPermCount = 1;
    map<char, int> m;
    int size = s.size();
    for (int i = size - 1; i > -1; i--)
    {
        char x = s[i];
        m[x]++;
        for (auto it = m.begin(); it != m.find(x); it++)
                rank += suffixPermCount * it->second / m[x];

        suffixPermCount *= (size - i);
        suffixPermCount /= m[x];
    }
    return rank;
}
叶经略
2023-03-14

如果我们使用数学,复杂性将会降低,并且能够更快地找到等级。这对于大型字符串特别有用。(更多详细信息可在此处找到)

鄢博简
2023-03-14

注:此答案适用于以1为基础的排名,如示例所示。下面是一些Python,它至少适用于所提供的两个示例。关键的事实是subfixperms*ctr[y]//ctr[x]是排列的数量,其第一个字母是y长度的(i 1)后缀。

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)
 类似资料:
  • 基于当前的实现,我将从某个来源获得一个数组列表,其中包含大约1000个按字母排序的唯一名称(A-Z或Z-A)。 我需要找到以给定字母表开头的第一个单词的索引。 因此,更准确地说,当我选择一个字母表,例如“M”时,它应该给我排序列表中以“M”开头的单词第一次出现的索引。 这样我就可以找到26个字母中每个字母开头的所有单词的索引。 请帮我找到一个不影响速度的解决方案。 更新时间: 实际上,在获得100

  • 这是我的数据样本 我编写了以下代码,它删除了所有分类列(例如)。但是,一些非类别列具有值。如何将它们从我的数据集中排除。 当我运行程序时,我得到错误来说太大的值,我认为这是由于值造成的。 问题1-我如何完全删除这些行问题2-这些列的类型是什么,大部分是NO。但两者之间有短信吗?我想我将执行,但这并没有给出结果

  • 我有这个字符串列表 我想根据其中的数字对这个列表进行排序。 例如,如果我有,我希望它像一样排序。 我使用了,但它返回类似的内容。 我应该怎么做才能把它按正确的顺序排列?

  • 问题内容: 这个问题已经在这里有了答案 : 如何使用SQL Order By语句对不区分大小写的结果进行排序? (3个答案) 4年前关闭。 我要做的就是按字母顺序抓取东西,而忽略大写字母。 这是我在上面使用的代码,但是它总是给我一个SQLite异常,表明COLLATE是语法错误。 android.database.sqlite.SQLiteException:在“ COLLATE”附近:语法错误:

  • 我有一个表,有以下列 我想要一个查询(下面查询的修改版本),如果上面的表中给定的work_date和员工ID(GROUP BYEMP_ID和WORK_DATE)超过1行,它将返回一行。所以我写了如下查询: 例如: 如果我通过1/1/2013 for:p_WorkDate,查询应返回如下: 基本上,我试图找出EMP\u ID和WORK\u DATE是否有超过1行,但还有一个额外的要求,即元素列包含什

  • 我有很多数据在一个目录,我想找到任何实例的双字不是数字。我从这里开始: 并将其扩展到包括我不希望在结果中出现的内容: 要忽略的样本数据: 比重1点零零七

  • 问题内容: 在java中查找字符串的所有排列 问题答案: 在这篇文章中,我们将看到如何在 java 中找到 String 的所有排列。 我们将使用一种非常简单的方法来做到这一点。 取出String的第一个字符,递归地插入剩余String的排列的不同位置。 假设您将 String 作为ABC。 所以我们从 ABC 中取出 A 第一个字符 =A 和 RemainingString = BC 因为我们在

  • 问题内容: 我是Java的新手,正在尝试按字母顺序排列术语的arrayList。(一个术语定义为一个字符和一个整数)(例如 我的代码如下: 为什么这不起作用?以及我该如何完成呢?我的arrayList称为术语,填充有Term类型 问题答案: 您在这行代码中遇到的问题。您的课程不是So 的类型,这两个对象将基于哪个属性或条件方法? 您必须使您的类为Comparable类型。和,根据您的需要覆盖该方法