Python max() vs if else

Preface

This post discusses some interesting findings about max() and if...else when comparing 2 elements. I have this doubt while doing LeetCode Problem 53. Maximum Subarray.

Introduction

LeetCode Problem 53:

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. (A subarray is a contiguous part of an array.)

My first attempt to this question is:

1
2
3
4
5
6
7
8
def solution(nums):
max_sum, temp = float('-inf'), 0

for num in nums:
temp = max(temp + num, num)
max_sum = max(max_sum, temp)

return max_sum

This solution’s runtime is 1101ms which only beats 38.56% of Python3 submissions. To further optimize the runtime, I changed to the solution below:

1
2
3
4
5
6
7
8
9
10
def solution(nums):
max_sum, temp = float('-inf'), 0

for num in nums:
temp = max(temp + num, num)

if temp > max_sum:
max_sum = temp

return max_sum

After reducing some unnecessary computations from max(), this solution has a runtime of 696ms which beats 96.94% of Python3 submissions. Then I have a question of which method is faster when comparing just 2 elements.

Experiment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import time

count, num_1, num_2 = 10**8, 1, 2

start = time.time()
for _ in range(count):
r = num_1 if num_1 > num_2 else num_2
res_if = time.time() - start

start = time.time()
for _ in range(count):
r = max(num_1, num_2)
res_max = time.time() - start

print(f"res_if:{res_if}; res_max:{res_max}")

#Result on my computer:
#res_if:9.846304178237915; res_max:23.544015884399414

As we have observed, using if...else is much faster than max() when comparing 2 elements.

Research

My first thought is even for just two elements, max() still needs to loop through the two elements, which is a huge time for large number of calls, but for if...else, the comparison is direct and fast.

However, after research online, this Stack Overflow Answer provides another perspective:

because max involves a dictionary lookup for the function name, then a function call, whereas direct < operator does not.

In his answer, the person also points out similar questions like Why is dict.get() slower than dict[key]? and Why is [] faster than list(). These two related questions have the similar answer, where a dictionary lookup for the function name is performed.

Code Practice

To be honest, before noticing this performance issue on that LeetCode question, I was just blindly using max() for all scenarios. In the future, if I need to get the larger element from just 2 elements, I would use the if...else syntax for its slight faster speed. However, for getting the largest element from more than 2 elements, max() is preferred for readability purpose.