在O(nlogn)时间内对两个字符串进行排序后,您可以找到2个字符串是字符串,但是可以在o(n)时间和O(1)空间中找到它。
答案 0 :(得分:6)
这里绝对没有专家......
但是为什么不通过每个字符串来简单计算每个字母出现的次数。
如果适当实施,这不应超过O(n)时间。
答案 1 :(得分: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)
[[编辑]] ,与上述相同,但有时间分析注释:
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
答案 2 :(得分:4)
生成素数数组[26]每个素数代表一个字符,然后当你遍历字符串时,多个每个字符的素数,如果相等,则为anagrams,否则不是。需要O(n)和恒定空间
答案 3 :(得分:4)
有几种方法可以解决它。
方法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相等,则字符串为anagrams。这个方法类似于Jin提到的解决方案,因为它在某种程度上为string生成hashCode。
时间复杂度 - O(n)
方法2 - 使用Character和Integer的hashmap
将2个字符串视为2个字符数组。遍历第一个数组,将字符添加到char的hashmap并计数,在找到字符时递增计数。同样遍历第二个数组,减少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
}
答案 4 :(得分: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);
}
}
答案 5 :(得分: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;
}
以下代码段会检查正确的字符,并根据需要转换大小写。第二次和第三次检查会考虑字符串是否有不同的长度
答案 6 :(得分:0)
如果按排序顺序转换单词字符并散列字符串。排序后具有相同哈希的每个字符串将是另一个字谜(非常可能,总是有碰撞的机会)。
答案 7 :(得分:0)
上述代码无法在所有条件下工作
我们可以快速排序并比较数组,同时消除空间
答案 8 :(得分:0)
此处的所有建议都倾向于使用相同的方法对输入字符串进行排序,然后比较结果。最常感兴趣的是常规的ascii字母,这可以通过计数排序进行优化,这似乎是大多数回答者的方法。计数排序可以在O(n)中对数字/整数的有限字母表进行排序,因此从技术上讲它是正确的答案。如果我们必须考虑之后遍历计数数组的时间,它将包括字母表的时间,使O(m + n)在字母表为UTF-32的情况下更加正确。
我倾向于认为最普遍正确的方法需要O(n lg n),因为如果字母表不能被充分限制,快速排序可以实时更快地证明。
答案 9 :(得分: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;
}
答案 10 :(得分: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,那么我们要么是重复的字符,要么是另一个字符串中不存在的字符,这意味着它不是字谜。
答案 11 :(得分:-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字符)。如果它们是字谜,则计数将等于零。
但这并不能解释插入空格的字谜。