Anagram时间复杂度

时间:2013-12-20 16:50:31

标签: string substring time-complexity anagram

我正在尝试解决以下问题

  

你有两个字符串。 A尺寸为n,B,尺寸为m。米是非常非常的   与n相比较少。找出A是否包含子串   是B的字谜。

我采取的方法如下

public static boolean ana_check(String a, String b)
{
    int n=a.length();
    int m=b.length();
    boolean k;
    for(int i=0;i<=(n-m);i++){
        k= anagram((a.substring(i,i+m)),b);
        if(k)
            return true;
}
    return false;
}

正如你所看到的,我从字符串A的开头开始提取每个长度为m的字符串,并检查它是否是B的字谜。 为了检查anagram我为每个字符串构建了一个频率图,如果发现它们是相同的,我返回true。代码如下:

  public static boolean anagram(String s, String t) {
        // Strings of unequal lengths can't be anagrams
        if(s.length() != t.length()) {
            return false;
        }

        // They're anagrams if both produce the same 'frequency map'
        return frequencyMap(s).equals(frequencyMap(t));
    }

    private static Map<Character, Integer> frequencyMap(String str) {
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for(char c : str.toLowerCase().toCharArray()) {
            Integer frequency = map.get(c);
            map.put(c, frequency == null ? 1 : frequency+1);
        }
        return map;
    }

我相信anagram方法在O(n)时间运行。 ana_check方法的时间复杂度是多少?整个代码是线性的还是二次的?

2 个答案:

答案 0 :(得分:2)

好吧,让我们看看......

假设length()方法在恒定时间内运行(即:它不像strlen()那样工作)。 你的方法frequencyMap是o(m),anagram调用它两次。字谜称为n-m次。 总复杂度大约为o(2 * m * n)。 m <&lt;&lt; n,'big o'是O(n)。

我可以建议一些优化。首先,您在每次调用anagram时重新生成字符串b的频率图。在ana_check的开头做一次。你可以有一个anagram方法,它采用字符串和频率图而不是两个字符串。

我要做的另一件事是从字谜中删除长度检查。是的,这是一个安全功能,但您已经知道传入的字符串大小相同。无论如何,如果它们的长度不同,频率图仍然不匹配,因此功能正确。

更棘手的优化是修改字符串a的频率图,而不是每次都重新进行。对于第一个子字符串,您可以照常执行。但是你向前移动一个角色,从地图中减去第一个角色并添加新角色。当然,如果m <= 3则不会产生影响,但任何大于此的东西都将是胜利。

答案 1 :(得分:0)

您无需比较每个位置的整个地图。

首先创建一个签名的频率图并减去每个字母 在B。保留一个计数器c,其中包含多少个非零条目 在地图上。

接下来,将m的{​​{1}}个字母B添加到地图中。对于 您添加的每个字母,如果该计数过去为零,则递增A, 或者如果在添加完字母后它变为零,则递减c

如果c现在为零,那么你就找到了一个字谜(每个负数 来自c的来自B的积极计数平衡了,否则 继续。

A的下一个字母添加到频率图中,然后删除该字母 在此之前发出A个字母,对两者进行适当调整m 操作

重复最后两步,直到c变为零或用完为止 c中的字母。

您可以尝试通过每次识别来进一步优化这一点 你添加一个没有出现在A中的角色,你可以保证一个 不匹配下一个B个字符(这与计数只是正数的位置不同,因为您传递的其他字符可能会在m之前取消)。所以你可以重启 这封信后的先决条件。操作的复杂性 这允许你跳过不是很高,但这和特殊情况 代码可能不会更快。