4

在 O(nlogn) 时间对两个字符串进行排序后,您可以找到 2 个字符串是否是字谜,但是是否有可能在 o(n) 时间和 O(1) 空间中找到它。

4

12 回答 12

5

生成一个素数数组[26] 每个素数代表一个字符,然后在遍历字符串时,将每个字符的素数相乘,如果相等,则为字谜,否则不。它需要 O(n) 和恒定空间

于 2012-09-09T18:42:06.430 回答
5

这里绝对没有专家...

但是为什么不检查每个字符串并简单地计算每个字母出现的次数。

给定适当的实现,这不应该超过 O(n) 时间。

于 2011-07-11T05:32:17.850 回答
5

有几种方法可以解决它。

方法 1 - 使用自定义哈希码函数
我们可以使用 hashCode 函数,例如:

static int[] primes = {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};
static String alphabet = "abcdefghijklmnopqrstuvwxyz";


public static int hashCode(String s){
    int sum = 0;

    for(char c: s.toCharArray()){
      sum += primes[c-97];
    }
    return sum;
}

生成两个字符串的哈希,如果 hashCode 相等,则字符串为字谜。这种方法类似于 Jin 提到的解决方案,因为它以某种方式为字符串生成 hashCode。
时间复杂度 - O(n)

方法 2 - 使用 Character 和 Integer 的 hashmap 将
2 个字符串视为 2 个字符数组。遍历第一个数组,将字符添加到char和count的hashmap中,找到字符后增加计数。同样遍历第二个数组,减少哈希图中的计数器,或者如果你没有找到字符,它们不是字谜。最后,当 map 包含所有字符并且计数为 0 时,那么 2 个字符串又是字谜。

方法 3 - 使用计数数组(我最喜欢的)


boolean are_anagrams(string1, string2){
 
    let counts = new int[26];
 
    for each char c in lower_case(string1)
        counts[(int)c]++
 
    for each char c in lower_case(string2)
        counts[(int)c]--
 
    for each int count in counts
        if count != 0
            return false
 
    return true
}

您可以在此处获取所有代码。

于 2014-04-26T12:04:57.863 回答
4

是的,使用哈希并计算出现次数。如果最后,我们有一个非零数字,那么字符串不是字谜。

let h => hash which maps letters to occurence_count (initialized to 0)

for each letter l in string a
  h[l] = h[l] + 1
end

for each letter l in string b
  h[l] = h[l] - 1
end

for each key l in h 
  return false if h[l] != 0
end

return true

这将在 O(n) + O(n) + c = O(n)中运行。我们的哈希包含 26 个字母的点,每个点都有一个与之关联的整数。因此空间为 O(26) = O(1)

[[Edit]],与上面相同,但带有时间分析注释:

let h => hash which maps letters to occurence_count (initialized to 0)

#this loop runs n times
for each letter l in string a
  #hash lookups / writes are constant time
  h[l] = h[l] + 1
end
#above function ran O(n) time

for each letter l in string b
  h[l] = h[l] - 1
end

#runs in O(alphabet) = O(c) = constant-time
for each key l in h 
  return false if h[l] != 0
end

return true
于 2011-07-11T05:32:45.297 回答
1

跑进 :O(n) + O(n) = O(n)

修复已用空间:O(256) = O(1)

这是Java中的代码

private static boolean isAnagramWithOneArray(String strFirst, String strSecond) {
    int[] charsCount = new int[256];

    if (strFirst != null && strSecond != null) {
        if (strFirst.length() != strSecond.length()) {
            return false;
        }
        for (int i = 0; i < strFirst.length(); i++) {
            charsCount[strFirst.charAt(i)]++;
            charsCount[strSecond.charAt(i)]--;
        }
        for (int i = 0; i < charsCount.length; i++) {
            if (charsCount[i] != 0) {
                return false;
            }
        }
        return true;
    } else {
        return (strFirst == null && strSecond == null);
    }
}
于 2013-01-16T08:10:28.760 回答
1
unsigned char CharacterCheck(char item)
{

    if ((item >= 'A') && (item <= 'Z'))
        return (item - 'A');

    if ((item >= 'a') && (item <= 'z'))
        return ((item - ('a' - 'A')) - 'A');

    return -1;

}

unsigned char AnagramCheck6 (char * item1, char * item2)
{
    char *test                      = item1;
    char *test2                     = item2;
    int count                       = 0;
    unsigned char rc                = 0;
    unsigned char rslt              = 0;

    while (*test && *test2)
    {
        rslt = CharacterCheck(*test++);

        if (rslt != 0xff)
            count += rslt;

        rslt = CharacterCheck(*test2++);

        if (rslt != 0xff)
            count -= rslt;
    }

    if (*test)
    {
        while (*test)
        {
            rslt = CharacterCheck(*test++);

            if (rslt != 0xff)
                count += rslt;
        }
    }

    if (*test2)
    {
        while (*test2)
        {
            rslt = CharacterCheck(*test2++);

            if (rslt != 0xff)
                count -= rslt;
        }
    }

    if (count)
        rc = 1;

    return rc;

}

以下代码段检查正确的字符并在需要时转换大小写。第二次和第三次检查会考虑字符串是否长度不同

于 2014-02-02T04:14:45.950 回答
0

上面的代码在所有情况下都无法工作

rateher 我们可以进行快速排序并在消除空格的同时比较数组

于 2013-01-10T17:13:07.793 回答
0

我会做如下的事情:

//is s an anagram of t?
#include <string>

bool is_anagram(const string& s, const string& t)
    {
    bool ret = false;

    //if s and t are anagrams, they must of same size
    if( s.length() != t.length() )
        {
        return ret;
        }

        //assume that s and t have valid ascii characters only
    char letters[ 256 ] = {0};
    int i;

    // find occurence of each character in string s
    for( i = 0; i < s.length(); i++ )
        {
        (letters[ s[i] ])++;
        }

    // now, find occurence of each character in string t, but decrement 
    // correspnding character
    for( i = 0; i < t.length(); i++ )
        {
        //if the count is <0 means the given character is not present in s
        if( --(letters[ t[i] ]) < 0 ) 
            {
            return ret;
            }
        }

    //out of for loop means success
    ret = true;
    return ret;
    }
于 2014-08-01T07:09:10.813 回答
0

如果您按排序顺序转换单词字符并散列字符串。排序后具有相同散列的每个字符串将是另一个的字谜(很可能,总是有冲突的机会)。

于 2011-07-11T05:31:33.270 回答
0

这里的所有建议都倾向于使用相同的方法对输入字符串进行排序,然后比较结果。对常规 ascii 字母最感兴趣,这可以通过计数排序来优化,这似乎是大多数回答者的方法。计数排序可以在 O(n) 中对有限的数字/整数字母表进行排序,因此从技术上讲它是正确的答案。如果我们必须考虑之后遍历计数数组的时间,它将包括字母表的时间,在字母表是 UTF-32 的情况下,使 O(m+n) 成为一个更正确的上限。

我倾向于认为最普遍正确的方法需要 O(n lg n),因为如果字母表不能被充分限制,快速排序可能会实时更快。

于 2014-04-26T12:18:12.087 回答
0

像这样使用python的东西?

def anagram(a,b):
    s1=list(a)
    s2=list(b)
    for i in s1:
        if i in s2:
            s2.remove(i)
    print(s2)
    return len(s2)==0

如果字符串不是彼此的字谜,这将返回 false。

为了避免使用像 remove 等内置插件,可以使用以下方法吗?

def hana(a,b):
    s1=list(a.lower())
    s2=list(b.lower())
    print(s1,s2)
    h={'a': 0, 'c': 0, 'b': 0, 'e': 0, 'd': 0, 'g': 0, 'f': 0, 'i': 0, 'h': 0, 'k': 0,'j': 0, 'm': 0, 'l': 0, 'o': 0, 'n': 0, 'q': 0, 'p': 0, 's': 0, 'r': 0, 'u': 0, 't': 0, 'w': 0, 'v': 0, 'y': 0, 'x': 0, 'z': 0}
    for i in s1:
        h[i]+=1
    for i in s2:
        h[i]-=1
    for key, val in h.items():
        if val != 0:
            return False
    return(True)

如果字符串是彼此的字谜,那么所有键的最终散列值应该为 0。如果它不是 0,那么我们有重复的字符或其他字符串中不存在的字符,这意味着它不是 anagram。

于 2021-05-15T19:23:44.050 回答
-1

也许是这样的:

    String str1 = "test";
    String str2 = "tzet";
    int count = 0;
    for (int i = 0; i < str1.length(); i++)
    {
        count = count + str1.charAt(i) - str2.charAt(i);
    }
    System.out.println(count);

从字符串 2 中减去每个字符,然后将字符串 1 中的每个字符相加到 count(假设 ASCII 字符)。如果它们是字谜,则计数将等于零。

不过,这不考虑插入空格的字谜。

于 2011-07-13T17:54:06.010 回答