如何证明两个字符串是彼此的排列?

时间:2014-06-11 06:03:36

标签: string algorithm char ascii permutation

我正在破解代码访谈书,我在数组和字符串章节中遇到了问题,他们要求编写一个方法,证明给出的两个字符串是彼此的排列。

书中的答案非常干净清晰。一种是排序,然后比较它们是否相同,另一种是检查两个字符串是否具有相同的字符数。

但是,我对这个问题采用了不同的方法,我希望与您分享以查看您的意见。

我假设这些字符是ASCII字符。 所以我想到的是首先检查两个字符串的长度是否相等,如果不是,我们直接返回false,因为很明显它反对排列的定义。

如果是这样,我们继续算法。首先,我们初始化:

int sum = 0;
int sum1 = 0;

然后我们浏览每个字符串的字符,将每个字符的ASCII值添加到总和中并比较最后的总和。如果他们相等,那么我们就得到了一个排列。

这种方法有效吗?

4 个答案:

答案 0 :(得分:5)

不,它不起作用,因为12既是210的总和,也是39的总和。< / p>

使用您的算法"ad"将是"bc"的排列。

在一般情况下,如果允许合理范围的字符和字符串长度,则没有真正的快捷方式。你提到的两个中最好的解决方案取决于语言。

答案 1 :(得分:2)

dystroy是对的

以99.999%的正确性(按您的方法)计算:

sum1 = sum (ASCII(i))
sum2 = sum (ASCII(i)^2)
sum3 = sum (ASCII(i)^3)
  • 对于两个字符串以及所有相同的动力和是否相同
  • 然后你有最有可能排列的字符串......

确保比较直方图(如你所提到的那样)但需要更多记忆...

答案 2 :(得分:2)

你的方法不会起作用,因为总和会有很多碰撞,基本上你假设的是5 + 3 = 8并且没有其他组合会产生8但是你错了例子4 + 4也是8。

有许多Ad hoc方法可以解决这个问题,我将描述其中的两个。 您可以使用素数代替通过类似于您的方法解决问题,或者只是分配2个数组并保留字符的记录。

1。你可以初始化2个大小为27的整数数组,每个数组分别为list1 [27],list2 [27]初始化为0,逐个字符地读取字符串,如果你读“c”从字符串1开始,递增list1的第3个元素,因为'c'是第三个字符,依此类推,当你完成读取两个字符串扫描时,如果存在任何不匹配,则两个数组都不匹配,它们不是彼此的排列。

可能的实现可以是

char str1[50]="permutation";
char str2[50]="importunate";

int list1[27]={0},list2[27]={0};


for(int i=0;i<11;i++){
    list1[(int)str1[i]-(int)'a'+1]++;
    list2[(int)str2[i]-(int)'a'+1]++;
}

for(int i=0;i<=27;i++){
    if(i==27){
        return true;
    }
    if(list1[i]!=list2[i])
    {
        return false;
    }
}

这种方法可以很容易地扩展到考虑空格,不同的大小写字符和数字。

2。此方法与您所做的类似,但它不使用ASCII值而是使用素数而不是添加它使用乘法。问题与您的方法有很多可能的碰撞作为破坏指出如果你选择乘法而你将再次遇到同样的问题,但是如果不是乘以ascii值,我们将分配给特定字符的素数乘以。

这里我们首先分配一个数组,它存储从2开始的前26个素数,并逐个字符地读取字符串并将分配给字符串的每个字符的所有相应的素数相乘,我们最终比较两个大的整数,如果这些是相等的,然后字符串是彼此的排列

可能的实施可能是

int arr[27]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103};
char str1[50]="permutation";
char str2[50]="importunate";

int prd1=1,prd2=1;


for(int i=0;i<11;i++){
    prd1=prd1*arr[(int)str1[i]-(int)'a'];
    prd2=prd2*arr[(int)str2[i]-(int)'a'];
}

if(prd1==prd2)
    return true;

else
    return false;

这个方法不像第一个那样可扩展,因为数字随着字符串的长度变大, 我们可以

prd1=prd1*arr[(int)str1[i]-(int)'a']%1000000009;
prd2=prd2*arr[(int)str2[i]-(int)'a']%1000000009;//or some other large prime number 

答案 3 :(得分:1)

使用sum无法实现这一点,因为数字没有唯一的和因子(如前面的答案所述)

这可以通过比较字符直方图

来完成

代码 Java

class Character_Histogram
{
    public Map<Character,Integer> histogram;

    public Character_Histogram ()
    {
        histogram = new TreeMap<Character,Integer> ();
    }

    public void count (Character c)
    {
        if (histogram.containsKey(c))
            histogram.put(c, histogram.get(c)+1);
        else
            histogram.put(c, 1);
    }

    public void count (String str)
    {
        for(char c : str.toCharArray())
            count(new Character(c));
    }
}