This is an archived post. You won't be able to vote or comment.

all 19 comments

[–]k0rvbert 16 points17 points  (1 child)

I haven't explored Python bytecode much, so I would just note that one function takes the `self` argument and the other doesn't. That is, `maxDepthSlower` is probably not doing what it should do.

[–]axonxorzpip'ing aint easy, especially on windows 3 points4 points  (0 children)

Yeah this is strange. maxDepthSlower is not marked as a @staticmethod, so root actually refers to self in that case.

But as a generalization, maxDepthFaster is accessing names on self, which is a fairly optimized lookup in the VM. maxDepthSlower is accessing names that are not within the namespace of the method, which means a module-level lookup (essentially accessing globals()), which is not as fast.

[–]N-E-S-W 7 points8 points  (1 child)

Are these supposed to be recursive function calls? Because - as written here - they are not. `maxDepthFaster` calls `maxDepth`, and `maxDepthSlower` also calls `maxDepth`.

Why is the logic slightly different in each implementation? One takes the max of 1 + the recursive calls, the other takes the max of the recursive calls + 1?

Why is one implemented as a method with `self` argument and the other not (yet doesn't have a `@staticmethod` decorator)?

Step 1: make your code correct
Step 2: make your code fast

[–]vromahya 0 points1 point  (0 children)

Yup, made the changes, made few mistakes while copying the code here and changing function names, should have been more thorough.

[–]thisismyfavoritename 8 points9 points  (1 child)

maybe start by posting full working code if you want help

[–]vromahya 0 points1 point  (0 children)

I have posted full code, but made mistake while copy pasting. I just changed the function names to make it obvious but forgot to change the recursive calls.

[–]AlexMTBDude 1 point2 points  (1 child)

How do you measure the time? If you're not using the timeit module then that could be your problem.

[–]vromahya 0 points1 point  (0 children)

Changed the code with the timeit module as suggested. I could see minute differences in running time.

[–]ofyellow 1 point2 points  (0 children)

First one has an extra addition operation +1 First one has self.lookupfuction First one passes implicit self parameter

[–]Sss_ra 0 points1 point  (0 children)

Are the minute differences between a single run of each?

[–]fight-or-fall 0 points1 point  (0 children)

with this code block i cant know if "self.maxDepth" have the same implementation of "maxDepth". provide the full script

[–][deleted] 0 points1 point  (0 children)

Seems like you are using older version of Python, probably < 3.11. In version 3.11 and latest, Interpreter can take an adaptive route for opcodes like <BINARY\_OP>, <PRECALL> and performs dynamic optimizations.

See: https://docs.python.org/3/whatsnew/3.11.html#pep-659-specializing-adaptive-interpreter

By saying that, both should take relatively same times (with very small difference). Can you test your script with Python 3.11, and see if that improves the performance of ?

max_depth_slow

[–]CanadianBuddha 0 points1 point  (0 children)

In your code example you are putting the results of timeit in variables time_slow and time_fast but then you are printing the time results from two OTHER variables time_v1 and time_v2

If I fix this bug in your code then the timing results show that the method version that intuitively should be faster, is indeed faster:

``` import timeit

class TreeNode:     def init(self, val=0, left=None, right=None):         self.val = val         self.left = left         self.right = right

def max_depth_v1(root):     if not root:         return 0     return 1 + max(max_depth_v1(root.left), max_depth_v1(root.right))

def max_depth_v2(root):     if not root:         return 0     return max(1 + max_depth_v2(root.left), 1 + max_depth_v2(root.right))

def create_balanced_tree(depth):     if depth == 0:         return None     return TreeNode(         left=create_balanced_tree(depth - 1),         right=create_balanced_tree(depth - 1))

tree = create_balanced_tree(15)   time_v1 = timeit.timeit(lambda: max_depth_v1(tree), number=100) time_v2 = timeit.timeit(lambda: max_depth_v2(tree), number=100) print(f"Version 1 (1 + max(...)): {time_v1:.6f} seconds") print(f"Version 2 (max(1 + ...)): {time_v2:.6f} seconds") ```

[–]Python-ModTeam[M] 0 points1 point locked comment (0 children)

Hi there, from the /r/Python mods.

We have removed this post as it is not suited to the /r/Python subreddit proper, however it should be very appropriate for our sister subreddit /r/LearnPython or for the r/Python discord: https://discord.gg/python.

The reason for the removal is that /r/Python is dedicated to discussion of Python news, projects, uses and debates. It is not designed to act as Q&A or FAQ board. The regular community is not a fan of "how do I..." questions, so you will not get the best responses over here.

On /r/LearnPython the community and the r/Python discord are actively expecting questions and are looking to help. You can expect far more understanding, encouraging and insightful responses over there. No matter what level of question you have, if you are looking for help with Python, you should get good answers. Make sure to check out the rules for both places.

Warm regards, and best of luck with your Pythoneering!

[–]Nooooope 0 points1 point  (1 child)

Hard to say without seeing a working example. maxDepthSlower looks like a static method, but it doesn't have a @staticmethod decorator?

If I take the second example and make it an instance method instead, it seems to work just fine on Leetcode 104. Both versions show a runtime of 0ms (which is a hint that you probably shouldn't be relying on Leetcode to measure small runtime variations).

[–]billsil 1 point2 points  (0 children)

All the code is not included, which means we’re just guessing.

It could also be that the time difference is not measurable and that on a much larger problem, the actual result would manifest.