【问题标题】:Java check if the string is an anagram of another string O ( log n )Java 检查字符串是否是另一个字符串 O ( log n ) 的字谜
【发布时间】:2016-02-16 04:16:04
【问题描述】:

所以我最近一直在研究与算法的运行时复杂性有关的所有内容,并想学习如何改变它们以在 n 的规模增加时提高效率,所以基本上我的目标是学习如何使事情 O (log n)。心想,我知道我这个小时可以做一个很好的小项目,那就是创建一个字谜检查器。

我翻阅了一些 SO 帖子,看到有人评论说,如果您将字母表中的每个字母都分配给一个数字,那么它可以成为 log n:

final Map<Character, Integer> map;
        String str = "hello";
        String check = "olleh";

        map = new HashMap<>();
        map.put('a', 2);
        map.put('b', 3);
        map.put('c', 4);
        map.put('d', 7);
        map.put('e', 11);
        map.put('f', 13);
        map.put('g', 17);
        map.put('h', 19);
        map.put('i', 23);
        map.put('j', 29);
        map.put('k', 31);
        map.put('l', 37);
        map.put('m', 41);
        map.put('n', 43);
        map.put('o', 47);
        map.put('p', 53);
        map.put('q', 59);
        map.put('r', 61);
        map.put('s', 67);
        map.put('t', 71);
        map.put('u', 73);
        map.put('v', 79);
        map.put('w', 83);
        map.put('x', 89);
        map.put('y', 97);
        map.put('z', 101);

然后我创建了方法:

 public static boolean isAnagram(String s, String check,Map<Character, Integer> map) {
        int stringTotal = 0;
        int checkTotal = 0;
        for(char ch: s.toCharArray()){
            int i = map.get(ch);
            stringTotal += ch;
        }
        for(char ch: check.toCharArray()){
            int i = map.get(ch);
            checkTotal +=ch;
        }
        if (stringTotal == checkTotal){
            return true;
        }
        return false;
    }

我相信这个方法是 O(n^2),因为它有两个独立的循环,我想不出创建这个 O(log n) 方法背后的逻辑。

任何指针都会很棒

【问题讨论】:

  • 仅供参考,两个独立的循环并不意味着 O(N^2)。想一想......你正在经历一个长度为 N 的数组两次(2N)。预先快速检查以确保您不会将时间花在昂贵的操作上,即在您的逻辑之前确保字符串的长度相等。
  • 哦,是的,当然@Tgsmith61591 感谢您指出这一点
  • 请查看此解决方案stackoverflow.com/a/42058276/379173

标签: java algorithm


【解决方案1】:

看起来是O(2n)n 一个接一个循环。如果你在n 的循环中嵌套一个n 的循环,你会得到O(n^2), 像这样:

int count = 0;
for ( int x = 0; x < n; x++ )
     for ( int y = 0; y < n; y++ )
         count++;

这里,count 将是 n*n 或 n2

在你粘贴的代码中,有两个循环:

int count = 0;
for ( int x = 0; x < n; x++ )
    count++;
for ( int y = 0; y < n; y++ )
    count++;

这里,countn+n 或 2n。

没有办法以此来创建O(log n) 函数,因为您总是需要检查所有n 值(所有字母)。

例如,假设我们计算出函数的精确 time complexitylog(n)(请注意,这与 order O(log n) 不同,后者消除了系数和更低订购条款)。
现在,如果n = 10;然后log(n) = 2.3(大约),如果你只看 2.3 个字母,你不能确定一个十个字母的词是另一个 10 个字母的词的变位词。

【讨论】:

  • 我会去掉最后一句,以“例如”开头。如果算法具有时间复杂度O(log n),则可能存在很大的比例常数。这并不意味着它读取2.3 个字符。
  • 我不关注.. 对于复杂度为O(log n) 的算法,其中n=10,它确实意味着算法检查log(10)2.3 字符。这是一个示例。对于n=1000log n 约为 6.9,所以我在这里看不到任何比例常数。你能澄清一下吗?
  • O(log n) 大约是随着 n 越来越大所花费的时间,因此 n 的特定值的单个示例永远无法证明它有或没有特定时间复杂。如果可以证明一个算法精确地采用了Math.floor(1000000 * log(n)) 步骤,那么时间复杂度将是O(log n),因为你可以忽略像1000000 这样的大因素。因此,您无法通过检查 2.3 个字符来读取长度为 10 的字符串这一事实并不重要。
  • 感谢您的回答和 cmets,那么对于这种情况,最有效的算法是 O (n log n) 吗?
  • @user3667111 不,您可以在O(n) 中进行操作。使用两个HashMap&lt;Character, Integer&gt; 计算出现次数,然后检查映射是否相等。
猜你喜欢
  • 2021-10-10
  • 2016-04-07
  • 2019-05-11
  • 1970-01-01
  • 2013-10-26
  • 2011-02-07
相关资源
最近更新 更多