代表一个单词与字母表

时间:2013-08-14 09:17:59

标签: algorithm data-structures count

这是一个采访问题:

Imagine an alphabet of words. Example:
a ==> 1
b ==> 2
c ==> 3
.
z ==> 26
ab ==> 27
ac ==> 28
.
az ==> 51
bc ==> 52
and so on.

这样字符序列只需要按升序排列(ab有效但ba不是)。给定任何单词如果有效则打印其索引,否则打印0。

Input Output
ab 27
ba 0
aez 441

注意:不允许使用暴力。以下是问题的链接:http://www.careercup.com/question?id=21117662

我可以理解这个解决方案:

  • 总字数为2 ^ 26 -1。
  • 对于给定的单词,首先出现小尺寸的单词。
  • 设n为单词的长度,
    • 大小小于n的单词总数为C(26,1)+ C(26,2)+ ... + C(26,n -1)
  • 然后计算在给定单词之前具有相同大小的单词数
  • 两个数字加上一个的总和就是结果

参考:sites.google.com/site/spaceofjameschen/annnocements/printtheindexofawordwithlettersinascendingorder--microsoft

在示例解决方案中,我理解作者如何计算大小小于word.size()的单词数。但是,在代码中,我不太确定如何在'word'之前找到与word.size()大小相同的单词数。

准确地说,这一点:

char desirableStart;  
i = 0;
while( i < str.size()){     
    desirableStart = (i == 0) ? 'a' : str[i - 1] + 1;   

    for(int j = desirableStart; j < str[i]; ++j){
        index += NChooseK('z' - j, str.size() - i - 1);     // Choose str.size() - i - 1 in the available charset
    }

    i ++;
}

有人可以帮我理解这一点吗?感谢。

2 个答案:

答案 0 :(得分:2)

首先(你可能得到了这个部分,但为了完整起见),NChooseK函数计算二项式系数,即从集合中选择 k 元素的方式的数量 n 元素。此功能在您的评论中称为C(n, k),因此我将使用相同的表示法。

由于字母是排序的而不是重复的,这正是可以创建问题中描述的 n - 字的方式的数量,所以这就是为什么函数的第一部分是让你在正确的位置:

int index = 0;
int i = 1;

while(i < str.size()) {
    // choose *i* letters out of 26
    index += NChooseK(26, i);
    i++;
}

例如,如果您的输入为aez,则会获得单词yz的索引,这是最后一个可能的2个字母组合:C(26, 1) + C(26, 2) = 351

此时,您拥有 n - 字词的初始索引,需要查看需要跳过的 n - 字词的组合数量到达这个词的结尾。要做到这一点,你必须检查每个单独的字母,并计算所有可能的字母组合,从前一个字母后面的一个字母开始(代码中的desirableStart变量),并以正在检查的字母结束。

例如,对于aez,您将按以下步骤操作:

  1. 获取最后两个字母的单词索引(yz)。
  2. 将索引加1(这实际上是在代码结束时完成的,但在此处更有意义的是保持正确的位置):现在我们处于abc的索引。
  3. 第一个字母是a,无需增加。你还在abc
  4. 第二个字母为e,计算从be的第二个字母的组合。这样就可以转到aef(请注意f是此示例中第一个有效的第3个字符,而desirableStart负责处理此问题。)
  5. 第三个字母为z,计算第3个字母的组合,从fz。这将使您进入aez
  6. 这就是代码的最后部分:

    // get to str.size() initial index (moved this line up)
    index ++;
    
    i = 0;
    while( i < str.size()) { 
    
        // if previous letter was `e`, we need to start with `f`
        desirableStart = (i == 0) ? 'a' : str[i - 1] + 1;   
    
        // add all combinations until you get to the current letter
        for (int j = desirableStart; j < str[i]; ++j) {
    
            char validLettersRemaining = 'z' - j;
            int numberOfLettersToChoose = str.size() - i - 1;
            index += NChooseK(validLettersRemaining, numberOfLettersToChoose);
        }
    
        i++;
    }
    
    return index;
    

答案 1 :(得分:0)

相同大小的单词数量与短单词对应单词的计算没有区别。

你可能会被c中从0开始的数组索引误入歧途。因此虽然i < str.size()可能暗示其他情况,但是这个循环的最后一次迭代实际上计算的单词的大小与其单词的大小相同。索引计算。