PHP 内置函数复杂度(isAnagramOfPalindrome 函数)
Posted
技术标签:
【中文标题】PHP 内置函数复杂度(isAnagramOfPalindrome 函数)【英文标题】:PHP built in functions complexity (isAnagramOfPalindrome function) 【发布时间】:2015-11-13 00:34:06 【问题描述】:过去 2 小时我一直在谷歌搜索,但我找不到 php 内置函数时间和空间复杂度的列表。我有isAnagramOfPalindrome 问题要解决,最大允许复杂度如下:
expected worst-case time complexity is O(N)
expected worst-case space complexity is O(1) (not counting the storage required for input arguments).
其中 N 是输入字符串的长度。这是我最简单的解决方案,但我不知道它是否在复杂性限制内。
class Solution
// Function to determine if the input string can make a palindrome by rearranging it
static public function isAnagramOfPalindrome($S)
// here I am counting how many characters have odd number of occurrences
$odds = count(array_filter(count_chars($S, 1), function($var)
return($var & 1);
));
// If the string length is odd, then a palindrome would have 1 character with odd number occurrences
// If the string length is even, all characters should have even number of occurrences
return (int)($odds == (strlen($S) & 1));
echo Solution :: isAnagramOfPalindrome($_POST['input']);
有人知道在哪里可以找到此类信息吗?
编辑
我发现array_filter
的复杂度为 O(N),count
的复杂度为 O(1)。现在我需要在count_chars
上查找信息,但是完整的列表对于将来的问题会非常方便。
编辑 2
在总体上对空间和时间复杂度进行了一些研究后,我发现这段代码具有 O(N) 时间复杂度和 O(1) 空间复杂度,因为:
count_chars
将循环 N 次(输入字符串的全长,开始复杂度为 O(N) )。这是生成一个最大字段数有限的数组(准确地说是 26 个,不同字符的数量),然后在这个数组上应用一个过滤器,这意味着过滤器最多循环 26 次。当将输入长度推向无穷大时,这个循环是微不足道的,它被视为一个常数。 Count 也适用于这个生成的常量数组,此外,它并不重要,因为count
函数的复杂度是 O(1)。因此,算法的时间复杂度为O(N)。
空间复杂度也是如此。在计算空间复杂度时,我们不计算输入,只计算过程中生成的对象。这些对象是 26 元素数组和 count 变量,它们都被视为常量,因为它们的大小不能超过这一点,无论输入有多大。所以我们可以说该算法的空间复杂度为 O(1)。
无论如何,该列表仍然很有价值,因此我们不必查看 php 源代码。 :)
【问题讨论】:
可能你得看源代码自己搞清楚。这是一个声称为某些功能提供此信息的问题的答案:***.com/questions/2473989/… 我遇到了这个,很棒的信息,但仅限于array_filter
,count
和 count_chars
上没有任何内容。
从技术上讲,有超过 26 个不同的字符。除非保证您的问题只提供英文字母表中的字符,否则 count_chars() 的最坏情况空间复杂度将是 min(N, 不包含此信息的一个可能原因是可能会在每个版本中发生变化,因为已针对一般情况进行了改进/优化。
PHP 是基于 C 构建的,其中一些函数只是 c 对应物的包装器,例如 hypot
谷歌搜索,查看 man hypot
,在数学库的文档中
http://www.gnu.org/software/libc/manual/html_node/Exponents-and-Logarithms.html#Exponents-and-Logarithms
来源实际上没有提供更好的信息 https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/math/w_hypot.c(非官方,链接方便)
别说,这只是glibc,Windows会有不同的实现。所以每个操作系统甚至可能有一个不同的大 O 编译 PHP
另一个原因可能是因为这会让大多数开发人员感到困惑。 我认识的大多数开发人员只会选择具有“最佳”大 O 的函数
最大值并不总是意味着它更慢
http://www.sorting-algorithms.com/
对某些函数发生的事情有很好的视觉支持,即冒泡排序是一种“慢”排序,但对于几乎排序的数据来说,它是最快的排序之一。 快速排序是许多人会使用的,这对于几乎排序的数据实际上非常慢。 大 O 是最坏的情况 - PHP 可能会在一个版本之间做出决定,他们应该针对特定条件进行优化,这将改变函数的大 O,并且没有简单的方法来记录它。
这里有一个部分列表(我猜你已经看到了)
List of Big-O for PHP functions
其中列出了一些更常见的 PHP 函数。
对于这个特定的例子......
不使用内置函数也很容易解决。
示例代码
function isPalAnagram($string)
$string = str_replace(" ", "", $string);
$len = strlen($string);
$oddCount = $len & 1;
$string = str_split($string);
while ($len > 0 && $oddCount >= 0)
$current = reset($string);
$replace_count = 0;
foreach($string as $key => &$char)
if ($char === $current)
unset($string[$key]);
$len--;
$replace_count++;
continue;
$oddCount -= ($replace_count & 1);
return ($len - $oddCount) === 0;
利用奇数不能超过 1 个这一事实,您可以提前从数组中返回。
我认为我的也是 O(N) 时间,因为据我所知,最坏的情况是 O(N)。
测试
$a = microtime(true);
for($i=1; $i<100000; $i++)
testMethod("the quick brown fox jumped over the lazy dog");
testMethod("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
testMethod("testest");
printf("Took %s seconds, %s memory", microtime(true) - $a, memory_get_peak_usage(true));
使用非常旧的硬件运行测试 我的方式
Took 64.125452041626 seconds, 262144 memory
你的方式
Took 112.96145009995 seconds, 262144 memory
我很确定我的方式也不是最快的方式。
对于 PHP 以外的语言(例如 Java),我实际上看不到太多信息。
我知道这篇文章的很多内容都在猜测为什么它不存在,并且没有很多来自可靠来源的资料,我希望它可以部分解释为什么大 O 没有列在文档页面中
【讨论】:
事后思考。您可能应该将字符串小写,因为这两种方法目前处理大小写的方式不同 这种信息存在于python中,所以我认为它可能也存在于php中......无论如何,这很有价值,我的第一个解决方案是没有内置函数,这种方式看起来更好,但我从没想过它可以产生如此大的差异(几乎翻倍)。以上是关于PHP 内置函数复杂度(isAnagramOfPalindrome 函数)的主要内容,如果未能解决你的问题,请参考以下文章