22

I've been googling for the past 2 hours, and I cannot find a list of php built in functions time and space complexity. I have the isAnagramOfPalindrome problem to solve with the following maximum allowed complexity:

expected worst-case time complexity is O(N)

expected worst-case space complexity is O(1) (not counting the storage required for input arguments).

where N is the input string length. Here is my simplest solution, but I don't know if it is within the complexity limits.

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']);

Anyone have an idea where to find this kind of information?

EDIT

I found out that array_filter has O(N) complexity, and count has O(1) complexity. Now I need to find info on count_chars, but a full list would be very convenient for future porblems.

EDIT 2

After some research on space and time complexity in general, I found out that this code has O(N) time complexity and O(1) space complexity because:

The count_chars will loop N times (full length of the input string, giving it a start complexity of O(N) ). This is generating an array with limited maximum number of fields (26 precisely, the number of different characters), and then it is applying a filter on this array, which means the filter will loop 26 times at most. When pushing the input length towards infinity, this loop is insignificant and it is seen as a constant. Count also applies to this generated constant array, and besides, it is insignificant because the count function complexity is O(1). Hence, the time complexity of the algorithm is O(N).

It goes the same with space complexity. When calculating space complexity, we do not count the input, only the objects generated in the process. These objects are the 26-elements array and the count variable, and both are treated as constants because their size cannot increase over this point, not matter how big the input is. So we can say that the algorithm has a space complexity of O(1).

Anyway, that list would be still valuable so we do not have to look inside the php source code. :)

Community
  • 1
  • 1
Skatch
  • 2,112
  • 2
  • 14
  • 32
  • Probably you have to look at the source code and figure it out for yourself. Here's a question with an answer that claims to give this information for some functions: http://stackoverflow.com/questions/2473989/list-of-big-o-for-php-functions – developerwjk Aug 19 '15 at 15:48
  • I ran into that, great info, but only for `array_filter`, nothing on `count` and `count_chars`. – Skatch Aug 19 '15 at 15:51
  • Technically, there are more than 26 different characters. Unless your problem is guaranteed to only supply characters from the English alphabet, your worst-case space complexity for count_chars() will be min(N, ). Also, don't forget to take upper/lower case into account... – Snild Dolkow Aug 21 '15 at 19:34
  • There is a list in this question: http://stackoverflow.com/questions/2473989/list-of-big-o-for-php-functions – VolenD Aug 21 '15 at 19:52
  • @Skatch I suggest that you answer your questions with the resources about complexities. – Nick Louloudakis Aug 21 '15 at 23:22
  • I would like to contribute to this question, but before, I would like to clarify a minor detail. It seems that I have misunderstand some thing, palindrome of test is "testset". I have tested both the class and the method in the answer, both return true for "testest" and "testset"? regarding to (palindromelist.net) it should be "testset". Is that correct? Or have I misunderstand it? – Maytham Fahmi Aug 22 '15 at 09:02
  • maytham, the function determines if the input string can be rearranged to make a palindrome, not if it is one. Snild, this is a practice assignment which said the input can be only lowercase letters, the applicability of the function in actual code is not the issue. Nick, I don't understand what you are saying? – Skatch Aug 22 '15 at 14:36
  • @maytham it works on the letters. Ie "tteesstt" or "ttttssee" would also return true as they can be rearranged to be a palindrome – exussum Aug 22 '15 at 20:13
  • @exussum my point was the palindrome for test is testset and not testest? or is it both? – Maytham Fahmi Aug 22 '15 at 20:22
  • Its testset or testtset if you reverse the word its will be the same. (Difference is the double t ) – exussum Aug 22 '15 at 20:23
  • @maytham please check the link with the task for clarification http://stackoverflow.com/questions/4628386/what-is-the-best-algorithm-to-find-whether-an-anagram-is-of-a-palindrome – Skatch Aug 22 '15 at 20:48
  • @exussum ok thanks guys – Maytham Fahmi Aug 22 '15 at 21:13
  • You don't have a complexity issue here, but just using slow functions (array_filter with userland callback). `$odds = 0; foreach (count_chars($S, 1) as $num) $odds += 1 - ($num & 1);` should be much, much faster here. – bwoebi Sep 04 '15 at 00:29
  • I don't think your way will make a difference as `array_filter` runs 26 times at most (so does `foreach`), and count chars will still have O(N) complexity. Anyway, the question is about the php built-in function complexity list, not the actual solution optimization. :) – Skatch Sep 04 '15 at 08:23

1 Answers1

5

A probable reason for not including this information is that is is likely to change per release, as improvements are made / optimizations for a general case.

PHP is built on C, Some of the functions are simply wrappers around the c counterparts, for example hypot a google search, a look at man hypot, in the docs for he math lib http://www.gnu.org/software/libc/manual/html_node/Exponents-and-Logarithms.html#Exponents-and-Logarithms

The source actually provides no better info https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/math/w_hypot.c (Not official, Just easy to link to)

Not to mention, This is only glibc, Windows will have a different implementation. So there MAY even be a different big O per OS that PHP is compiled on

Another reason could be because it would confuse most developers. Most developers I know would simply choose a function with the "best" big O

a maximum doesnt always mean its slower

http://www.sorting-algorithms.com/

Has a good visual prop of whats happening with some functions, ie bubble sort is a "slow" sort, Yet its one of the fastest for nearly sorted data. Quick sort is what many will use, which is actually very slow for nearly sorted data. Big O is worst case - PHP may decide between a release that they should optimize for a certain condition and that will change the big O of the function and theres no easy way to document that.

There is a partial list here (which I guess you have seen)

List of Big-O for PHP functions

Which does list some of the more common PHP functions.

For this particular example....

Its fairly easy to solve without using the built in functions.

Example code

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;

}

Using the fact that there can not be more than 1 odd count, you can return early from the array.

I think mine is also O(N) time because its worst case is O(N) as far as I can tell.

Test

$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));

Tests run using really old hardware My way

Took 64.125452041626 seconds, 262144 memory

Your way

Took 112.96145009995 seconds, 262144 memory

I'm fairly sure that my way is not the quickest way either.

I actually cant see much info either for languages other than PHP (Java for example).

I know a lot of this post is speculating about why its not there and theres not a lot drawing from credible sources, I hope its an partially explained why big O isnt listed in the documentation page though

Community
  • 1
  • 1
exussum
  • 18,275
  • 8
  • 32
  • 65
  • As an after thought. You should probably lower case the strings as both methods currently handle upper and lower case differently – exussum Aug 21 '15 at 23:20
  • 1
    This kind of information exists for python, so I thought it may exist for php too... Anyway, this is valuable, my first solution was without built-in functions and this way looked way better, but I never thought it can make such a big difference (almost double). – Skatch Aug 22 '15 at 14:23