寻找字谜

时间:2019-03-03 18:07:20

标签: c string anagram

rm -rf /tmp/haste-map-react-native-packager-*

这是一个代码段,用于检查2个字符串是否为字谜。在这里如何处理重复的字符?另外,可以使该程序更优化吗?这段代码的运行时复杂度是多少?

3 个答案:

答案 0 :(得分:2)

首先,这不是正确的解决方案。考虑以下两个字符串:“ aabc”和“ aade” a [0] == b [0],a [0] == b [1],a [1] == b [0]和a [1] == b [1]。 len为4,但不是七字谜。复杂度是O(n ^ 2)为字符串长度的n。

@Sulthan回答了您,一种更好的方法是对复杂度为O(n * log(n))的字符串进行排序,然后一次性比较两个字符串O(n)。

要在O(n * log(n))中对字符串进行排序,您不能使用冒泡方法,但可以使用合并排序,如下所述:https://www.geeksforgeeks.org/merge-sort/

一种更好的方法是创建一个整数数组,在该数组中,您计算​​第一个字符串中每个字符的出现次数,然后为第二个数组中的每个出现次数减去一个出现次数。最后,辅助数组的所有位置必须为0。

答案 1 :(得分:2)

最佳解决方案可能是基于计算每个字符串中的字符数,然后比较两个计数。理想情况下,我们应该使用 Dictionary 数据结构,但为简单起见,我将在数组上演示该算法:

char *word1 = "word1";
char *word2 = "ordw1";

// C strings can have only 256 possible characters, therefore let's store counts in an array with 256 items.
int* letterCounts1 = calloc(256, sizeof(int));
int* letterCounts2 = calloc(256, sizeof(int));
size_t length1 = strlen(word1);
size_t length2 = strlen(word2);

for (size_t i = 0; i < length1; i++) {
    int letterIndex = word1[i] & 0xFF;
    letterCounts1[letterIndex] += 1;
}

for (size_t i = 0; i < length2; i++) {
    int letterIndex = word2[i] & 0xFF;
    letterCounts2[letterIndex] += 1;
}

bool isAnagram = true;

for (size_t i = 0; i < 256; i++) {
    if (letterCounts1[i] != letterCounts2[i]) {
        isAnagram = false;
        break;
    }
}

free(letterCounts1);
free(letterCounts2);

if (isAnagram) {
    printf("Anagram");
} else {
    printf("Not anagram");
}

此算法具有线性(O(n))复杂度(“字典”上的迭代可以视为常量)。

您原始的解决方案具有二次复杂度,但是,您还必须确保将strlen的结果存储到变量中,因为对strlen的每次调用都必须遍历整个字符串,从而增加了对立方。

答案 2 :(得分:1)

以下是一些答案:

  • 您的算法不会处理重复的字母,它可能会返回误报。
  • 不清楚是否正确,因为您没有发布包含所有声明和定义的完整函数定义,尤其是len是否初始化为0
  • 它具有 O(N 2 的时间复杂度,甚至 O(N 3 无法优化对strlen()的大量冗余调用。

这是具有线性复杂度的8位字符系统的简单解决方案:

#include <stdio.h>
#include <string.h>

int check_anagrams(const char *a, const char *b) {
    size_t counters[256];
    size_t len = strlen(a);
    size_t i;

    if (len != strlen(b)) {
        printf("Not anagrams\n");
        return 0;
    }
    for (i = 0; i < 256; i++) {
        counters[i] = 0;
    }
    for (i = 0; i < len; i++) {
        int c = (unsigned char)a[i];
        counters[c] += 1;
    }
    for (i = 0; i < len; i++) {
        int c = (unsigned char)b[i];
        if (counters[c] == 0) {
            printf("Not anagrams\n");
            return 0;
        }
        counters[c] -= 1;
    }
    printf("Anagrams\n");
    return 1;
}