Skip to main content
Code Review

Return to Answer

Commonmark migration
Source Link

###Things you could improve without significantly changing your code

Things you could improve without significantly changing your code

###Things you could improve without significantly changing your code

Things you could improve without significantly changing your code

added 405 characters in body
Source Link
wvxvw
  • 1k
  • 7
  • 14
  1. Do not compare to None using ==. Use variable is None instead. See this document for rationale: https://www.python.org/dev/peps/pep-0008/#id51
  2. countSmaller should use snake case: count_smaller (similar convention).
  3. res[::-1] - creates a reversed copy, which you don't need, since res is a local variable, which is not shared with other functions. You could use res.reverse() instead, saving some memory allocations.
  4. Names of classes need to be in Pascal case, i.e. count_smallerbst_node needs to be CountSmallerBSTNode.

###Things you could improve without significantly changing your code

  1. If you are after performance: don't use classes. Use tuple or namedtuple (see here: https://docs.python.org/2/library/collections.html#collections.namedtuple ). There's no reason bst_node should be a class.
  2. Invoking class method is also expensive, but you have nothing to gain from add_node being a class method.
  1. Do not compare to None using ==. Use variable is None instead. See this document for rationale: https://www.python.org/dev/peps/pep-0008/#id51
  2. countSmaller should use snake case: count_smaller (similar convention).
  3. res[::-1] - creates a reversed copy, which you don't need, since res is a local variable, which is not shared with other functions. You could use res.reverse() instead, saving some memory allocations.
  4. Names of classes need to be in Pascal case, i.e. count_smaller needs to be CountSmaller.
  1. Do not compare to None using ==. Use variable is None instead. See this document for rationale: https://www.python.org/dev/peps/pep-0008/#id51
  2. countSmaller should use snake case: count_smaller (similar convention).
  3. res[::-1] - creates a reversed copy, which you don't need, since res is a local variable, which is not shared with other functions. You could use res.reverse() instead, saving some memory allocations.
  4. Names of classes need to be in Pascal case, i.e. bst_node needs to be BSTNode.

###Things you could improve without significantly changing your code

  1. If you are after performance: don't use classes. Use tuple or namedtuple (see here: https://docs.python.org/2/library/collections.html#collections.namedtuple ). There's no reason bst_node should be a class.
  2. Invoking class method is also expensive, but you have nothing to gain from add_node being a class method.
Source Link
wvxvw
  • 1k
  • 7
  • 14

Let's get some obvious stuff out of the way first:

  1. Do not compare to None using ==. Use variable is None instead. See this document for rationale: https://www.python.org/dev/peps/pep-0008/#id51
  2. countSmaller should use snake case: count_smaller (similar convention).
  3. res[::-1] - creates a reversed copy, which you don't need, since res is a local variable, which is not shared with other functions. You could use res.reverse() instead, saving some memory allocations.
  4. Names of classes need to be in Pascal case, i.e. count_smaller needs to be CountSmaller.

Some subtleties: Python actually has array type, rarely used and, to be honest, not very useful, but, maybe if you are required to return an array, it is what you should return (or just reflect on the level of competence of the person describing the problem).

Now, while, in principle it's hard for me to think about a theoretically better algorithm, notice that a naive solution given below performs better on even reasonably long lists than the one you have simply because all the memory allocation and function calls needed to support this tree structure you've built are so expensive:

import cProfile
import random
def count_smaller(nums):
 result = [0] * len(nums)
 for i, n in enumerate(nums):
 for j in nums[i+1:]:
 if j < n:
 result[i] += 1
 return result
def test_count_smaller(n, m):
 for _ in range(n):
 count_smaller(random.sample(range(m), m))
def test_countSmaller(n, m):
 for _ in range(n):
 Solution().countSmaller(random.sample(range(m), m))
cProfile.run('test_count_smaller(100, 50)')

Gives:

 18888 function calls in 0.019 seconds
 Ordered by: standard name
 ncalls tottime percall cumtime percall filename:lineno(function)
 100 0.011 0.000 0.011 0.000 <stdin>:1(count_smaller)
 1 0.000 0.000 0.019 0.019 <stdin>:1(test_count_smaller)
 1 0.000 0.000 0.019 0.019 <string>:1(<module>)
 300 0.000 0.000 0.000 0.000 _weakrefset.py:70(__contains__)
 200 0.000 0.000 0.000 0.000 abc.py:178(__instancecheck__)
 5000 0.003 0.000 0.005 0.000 random.py:229(_randbelow)
 100 0.002 0.000 0.007 0.000 random.py:289(sample)
 1 0.000 0.000 0.019 0.019 {built-in method builtins.exec}
 200 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance}
 200 0.000 0.000 0.000 0.000 {built-in method builtins.len}
 100 0.000 0.000 0.000 0.000 {built-in method math.ceil}
 100 0.000 0.000 0.000 0.000 {built-in method math.log}
 5000 0.000 0.000 0.000 0.000 {method 'bit_length' of 'int' objects}
 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
 7584 0.001 0.000 0.001 0.000 {method 'getrandbits' of '_random.Random' objects}

While your original code gives:

cProfile.run('test_countSmaller(100, 50)')
 59449 function calls (33812 primitive calls) in 0.030 seconds
 Ordered by: standard name
 ncalls tottime percall cumtime percall filename:lineno(function)
 1 0.001 0.001 0.030 0.030 <stdin>:1(test_countSmaller)
 100 0.004 0.000 0.022 0.000 <stdin>:14(countSmaller)
 5000 0.002 0.000 0.002 0.000 <stdin>:2(__init__)
30637/5000 0.016 0.000 0.016 0.000 <stdin>:2(add_node)
 1 0.000 0.000 0.030 0.030 <string>:1(<module>)
 300 0.000 0.000 0.000 0.000 _weakrefset.py:70(__contains__)
 200 0.000 0.000 0.000 0.000 abc.py:178(__instancecheck__)
 5000 0.003 0.000 0.004 0.000 random.py:229(_randbelow)
 100 0.002 0.000 0.007 0.000 random.py:289(sample)
 1 0.000 0.000 0.030 0.030 {built-in method builtins.exec}
 200 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance}
 100 0.000 0.000 0.000 0.000 {built-in method builtins.len}
 100 0.000 0.000 0.000 0.000 {built-in method math.ceil}
 100 0.000 0.000 0.000 0.000 {built-in method math.log}
 5000 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
 5000 0.000 0.000 0.000 0.000 {method 'bit_length' of 'int' objects}
 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
 7608 0.001 0.000 0.001 0.000 {method 'getrandbits' of '_random.Random' objects}
lang-py

AltStyle によって変換されたページ (->オリジナル) /