Anagram 算法目标 C

Posted

技术标签:

【中文标题】Anagram 算法目标 C【英文标题】:Anagram algorithm objective C 【发布时间】:2012-12-04 01:11:08 【问题描述】:

我编写了以下代码来检查 anagram 想知道这是完美的吗?有没有更好的方法在目标 C 中实现相同的功能

-(BOOL) findAnagram :(NSString *) string1 :(NSString *) string2

    int len = string1.length;
    if (len != string2.length)
    
        return false;
    

    for (int i=0; i < len; i++)
    
        int h = 0;
        int q = 0;
        for (int k = 0;  k < len ; k ++)
        
            if ([string1 characterAtIndex:i] == [string1 characterAtIndex:k])
            
                h++;
            
            if ([string1 characterAtIndex:i] == [string2 characterAtIndex:k])
            
                q++;
            
        

        if (h!=q)
        
            return false;
        
    
    return TRUE;

【问题讨论】:

这应该在代码审查网站上。 这个问题属于codereview.stackexchange.com 【参考方案1】:

一个比你的性能更好的版本,它是一个 O(n ^ 2) 算法,是一个 O(n) 算法:

BOOL anagrams(NSString *a, NSString *b)

    if (a.length != b.length)
        return NO;

    NSCountedSet *aSet = [[NSCountedSet alloc] init];
    NSCountedSet *bSet = [[NSCountedSet alloc] init];

    for (int i = 0; i < a.length; i++)
    
        [aSet addObject:@([a characterAtIndex:i])];
        [bSet addObject:@([b characterAtIndex:i])];
    

    return [aSet isEqual:bSet];

【讨论】:

+1 表示NSCountedSet。太多人不知道这个类甚至存在以及它可以用于什么(然后使用NSDictionaryNSNumber...呃) 你还需要小写,去掉非字母。像a = [[[a componentsSeparatedByCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] componentsJoinedByString:@""] lowercaseString]; 这样的东西。用于测试的示例字谜:“Tom Marvolo Riddle”、“I am Lord Voldemort”。 @Jano true,但我认为该特定细节已由 OP 实现。【参考方案2】:

您想知道两个字符串是否包含完全相同的字符?最简单的方法可能是对它们进行排序并比较排序后的版本。

另一种方法是计算每个字母出现的次数(有多少 As,多少 B,等等),然后比较这些次数。

(注意:第二种方式只是第一种方式的变体,是一种对字符串进行排序的有效方式)

【讨论】:

他的算法正在执行您的第二个想法,尽管它会检查两次或三次等,如果某个字符出现超过 1 次。【参考方案3】:

我觉得很好。但是代码风格有点奇怪。我会这样写:

- (BOOL)isStringAnagram:(NSString *)string1 ofString:(NSString *)string2 
    int len = string1.length;
    if (len != string2.length) 
        return NO;
    

    for (int i=0; i < len; i++) 
        int h = 0;
        int q = 0;
        for (int k = 0;  k < len; k++) 
            if ([string1 characterAtIndex:i] == [string1 characterAtIndex:k]) 
                h++;
            
            if ([string1 characterAtIndex:i] == [string2 characterAtIndex:k]) 
                q++;
            
        

        if (h != q) 
            return NO;
        
    

    return YES;

我遇到的主要问题是方法名称。虽然名称中可能有参数前面没有任何内容,但不建议这样做。即您使用 findAnagram:: 作为名称,而我使用的是 isStringAnagram:ofString:

【讨论】:

【参考方案4】:

这是对@zmbq 排序和比较建议的实现。

您应该考虑删除空格和不区分大小写的要求。

- (BOOL)isAnagram:(NSString *)leftString and:(NSString *)rightString 
  NSString *trimmedLeft = [[leftString stringByReplacingOccurrencesOfString:@" " withString:@""] lowercaseString];
  NSString *trimmedRight = [[rightString stringByReplacingOccurrencesOfString:@" " withString:@""] lowercaseString];
  return [[self stringToCharArraySorted:trimmedLeft] isEqual:[self stringToCharArraySorted:trimmedRight]];


- (NSArray *)stringToCharArraySorted:(NSString *)string 
  NSMutableArray *array = [[NSMutableArray alloc] init];
  for (int i = 0 ; i < string.length ; i++) 
    [array addObject:@([string characterAtIndex:i])];
  
  return [[array sortedArrayUsingSelector:@selector(compare:)] copy];

这样称呼

BOOL isAnagram = [self isAnagram:@"A BC" and:@"cba"];

【讨论】:

【参考方案5】:

检查以下检查 Anagram 字符串的方法。

-(BOOL)checkAnagramString:(NSString*)string1 WithAnotherString:(NSString*)string2

  NSCountedSet *countSet1=[[NSCountedSet alloc]init];
  NSCountedSet *countSet2=[[NSCountedSet alloc]init];

  if (string1.length!=string2.length) 
    NSLog(@"NOT ANAGRAM String");
    return NO;
  


  for (int i=0; i<string1.length; i++) 
      [countSet1 addObject:@([string1 characterAtIndex:i])];
      [countSet2 addObject:@([string2 characterAtIndex:i])];
  

  if ([countSet1 isEqual:countSet2]) 
    NSLog(@"ANAGRAM String");
    return YES;
   else 
    NSLog(@"NOT ANAGRAM String");
    return NO;
  


【讨论】:

【参考方案6】:

磨坊算法的另一个运行:

- (BOOL) testForAnagramWithStrings:(NSString *)stringA andStringB: (NSString *)stringB

    stringA = [stringA lowercaseString];

     stringB = [stringB lowercaseString];


     int counter = 0;

     for (int i=0; i< stringA.length; i++)


         for (int j=0; j<stringB.length;j++)


             if ([stringA characterAtIndex:i]==[stringB characterAtIndex:j])

                 counter++;

             


         

     

     if (counter!= stringA.length)

         return false;
     

     return true;


【讨论】:

以上是关于Anagram 算法目标 C的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode算法题-Valid Anagram(Java实现)

多目标遗传算法 ------ NSGA-II (部分源码解析) 交叉操作 crossover.c

我怎样才能加快这个 Anagram 算法

多目标遗传算法 ------ NSGA-II (部分源码解析)状态报告 打印 report.c

多目标遗传算法 ------ NSGA-II (部分源码解析)父子种群合并 merge.c

多目标遗传算法 ------ NSGA-II (部分源码解析)二元锦标赛选择 tourselect.c