最小复杂度的Anagram算法

我最近被要求设计一种算法来检查两个字符串是否是彼此的字谜。我的目标是最小化空间和时间复杂度,所以我提出了这个算法: 创建一个包含26个元素的数组,每个元素初始化为零。 遍历第一个字符串,对于每个字符,递增与该字符对应的数组元素。 遍历第二个字符串,对于每个字符,递减与该字符对应的数组元素。 扫描阵列。如果所有元素都是0,则两个字符串是字谜。 然而,该算法的时间复杂度为O(n),我无法提出复杂度较低的算法。有人知道吗?     
已邀请:
您的算法渐近最优。在Ω(n)时间内解决这个问题是不可能的。为了看到这一点,假设存在一个可以在o(n)时间内解决问题的算法A(请注意,这里的n很少)。然后对于任何1>ε > 0,存在一些n,使得对于任何大小至少为n的输入,算法必须最多以ε步骤终止。设置ε = 1/3并考虑算法的任何输入,其长度至少为n,对于前面提到的n,对于这个ε。由于算法可以查看两个字符串中大多数1/3的字符,因此函数必须有两个不同的输入,一个是一对字谜,另一个不是,这样算法会查看每个输入的相同字符的子集。然后,该函数必须在每种情况下产生相同的输出,因此在至少一个输入上将是错误的。我们已经达成了矛盾,所以不存在这样的算法。     
您可以通过早期退出提高平均绩效。扫描第二个字符串时,如果在递减之前count [char]为0,则表示没有anagram并且可以停止扫描。 此外,如果字符串短于26个字符,则在最后一步中,仅检查第一个字符串中的字符是否为零。 这不会改变大O,但它可以将平均运行时间改为小于建议解决方案的2N + 26,具体取决于您的数据。     
为了确保字符串是字谜你需要比较整个字符串 - 那么怎么能比o(n)更快?     
我们来问一个问题: 给定两个字符串s和t,写一个函数来确定t是否是s的字谜。 例如,s =“anagram”,t =“nagaram”,返回true。 s =“rat”,t =“car”,返回false。 方法1(使用HashMap):
    public class Method1 {

    public static void main(String[] args) {
        String a = "protijayi";
        String b = "jayiproti";
        System.out.println(isAnagram(a, b ));// output => true

    }

    private static boolean isAnagram(String a, String b) {
        Map<Character ,Integer> map = new HashMap<>();
        for( char c : a.toCharArray()) {
            map.put(c,    map.getOrDefault(c, 0 ) + 1 );
        }
        for(char c : b.toCharArray()) {
            int count = map.getOrDefault(c, 0);
            if(count  == 0 ) {return false ; }
            else {map.put(c, count - 1 ) ; }
        }

        return true;
    }

}
方法2:
    public class Method2 {
public static void main(String[] args) {
    String a = "protijayi";
    String b = "jayiproti";


    System.out.println(isAnagram(a, b));// output=> true
}

private static boolean isAnagram(String a, String b) {


    int[] alphabet = new int[26];
    for(int i = 0 ; i < a.length() ;i++) {
         alphabet[a.charAt(i) - 'a']++ ;
    }
    for (int i = 0; i < b.length(); i++) {
         alphabet[b.charAt(i) - 'a']-- ;
    }

    for(  int w :  alphabet ) {
         if(w != 0 ) {return false;}
    }
    return true;

}
}
方法3:
    public class Method3 {
public static void main(String[] args) {
    String a = "protijayi";
    String b = "jayiproti";


    System.out.println(isAnagram(a, b ));// output => true
}

private static boolean isAnagram(String a, String b) {
    char[] ca = a.toCharArray() ;
    char[] cb = b.toCharArray();
    Arrays.sort(   ca     );

    Arrays.sort(   cb        );
    return Arrays.equals(ca , cb );
}
}
方法4:
    public class Method4 {
public static void main(String[] args) {
    String a = "protijayi";
    String b = "jayiproti";
    //String c = "gini";

    System.out.println(isAnagram(a, b ));// output => true
}

private static boolean isAnagram(String a, String b) {
    Map<Integer, Integer> map = new HashMap<>();
    a.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) + 1));
    b.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) - 1));
    //System.out.println(map.values());

    for(int count : map.values()) {
       if (count<0) return false;

    }

    return true;
}
}
    
int anagram (char a[], char b[]) {

  char chars[26];
  int ana = 0;
  int i =0;

  for (i=0; i<26;i++)
        chars[i] = 0;


  if (strlen(a) != strlen(b))
        return -1;

  i = 0;
  while ((a[i] != '') || (b[i] != '')) {
        chars[a[i] - 'a']++;
        chars[b[i] - 'a']--;
        i++;
  }

  for (i=0; i<26;i++)
        ana += chars[i];

   return ana;

}


void main() {

  char *a = "chimmy";
  char *b = "yimmch";

  printf ("Anagram result is %d.n", anagram(a,b));


}
    

要回复问题请先登录注册