Skip to content

Commit 38954c6

Browse files
heikkitoivonencodex
andcommitted
Fix: Correct complexity documentation details
Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Codex <codex@openai.com>
1 parent b9fbcc5 commit 38954c6

9 files changed

Lines changed: 49 additions & 49 deletions

File tree

docs/builtins/chr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ chr(65) # 'A'
200200

201201
# TypeError - non-integer
202202
try:
203-
chr(65.0) # Works! Floats converted to int
203+
chr(65.0) # TypeError - float not accepted
204204
except TypeError:
205205
pass
206206

docs/builtins/int.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ The `int` type represents arbitrary precision integers. Python 3 has a single in
4949

5050
| Operation | Time | Space | Notes |
5151
|-----------|------|-------|-------|
52-
| `hash(x)` | O(1) | O(1) | Hash value |
52+
| `hash(x)` | O(n)* | O(1) | Iterates over internal digits; O(1) for compact one-digit ints (roughly \|x\| <= 2^30-1 on typical 64-bit builds) |
5353
| `str(x)` | O(n) | O(n) | Convert to string |
5454
| `repr(x)` | O(n) | O(n) | String representation |
5555
| `int(x)` | O(1) | O(1) | No-op if already int |

docs/builtins/sorted.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,14 @@ original.sort() # [1, 1, 3, 4, 5]
156156
### Expensive Key Functions
157157

158158
```python
159-
# O(n log n * k) - k = key function time
159+
# O(n*k + n log n) - key computed once per element, then cached
160160
def expensive_key(x):
161161
# O(m) - expensive computation
162162
return sum(range(x))
163163

164164
numbers = list(range(1000))
165165
result = sorted(numbers, key=expensive_key)
166-
# Complexity: O(n log n * m)
166+
# Complexity: O(n*m + n log n) - key called n times, then n log n comparisons
167167

168168
# Better: pre-compute keys
169169
from operator import itemgetter
@@ -180,7 +180,7 @@ def get_sort_key(item):
180180
# Some expensive computation
181181
return complex_calculation(item)
182182

183-
# Slow: O(n log n * k)
183+
# With key: O(n*k + n log n) - key computed once per element
184184
result = sorted(items, key=get_sort_key)
185185

186186
# Faster: O(n*k + n log n)

docs/builtins/tuple.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The `tuple` type is an immutable, ordered sequence. Being immutable allows vario
1414
| `copy()` | O(1) | O(1) | Just increments reference count |
1515
| `x + y` (concatenation) | O(m+n) | O(m+n) | m, n are lengths |
1616
| `t * n` (repetition) | O(n*len(t)) | O(n*len(t)) | Creates new tuple |
17-
| `hash()` | O(n) | O(1) | Computes hash by iterating all elements |
17+
| `hash()` | O(n) first call, O(1) cached | O(1) | Hash computed once then cached in `ob_hash` |
1818
| `reversed()` | O(1) | O(1) | Iterator, not materialized |
1919
| `tuple()` constructor | O(n) | O(n) | n = iterable length |
2020
| `slice [::2]` | O(k) | O(k) | k = slice length |
@@ -37,11 +37,11 @@ s = {(0, 0), (1, 1)}
3737
```python
3838
# hash() computes hash value by iterating all elements
3939
t = (1, 2, 3)
40-
h1 = hash(t) # O(n) - computes by iterating elements
40+
h1 = hash(t) # O(n) first call - computes by iterating elements
4141

42-
# Note: Unlike strings, tuples do NOT cache their hash
43-
# Each call recomputes: O(n) every time
44-
h2 = hash(t) # O(n) - recomputes hash
42+
# CPython caches the hash in the tuple's ob_hash field
43+
# Subsequent calls return the cached value
44+
h2 = hash(t) # O(1) - returns cached hash
4545
```
4646

4747
### Reference vs Copy

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ See [Built-in Types](builtins/list.md) for detailed analysis.
4949

5050
## Why Trust This Documentation?
5151

52-
This documentation has been reviewed and refined by multiple AI coding agents (Amp, Claude, Gemini CLI, Kiro, Copilot, Codex) and models (Opus 4.5, Sonnet 4.5, Gemini 3 Pro, gpt-5.2-codex, ...) working alongside human contributors. Each agent brings different perspectives and catches different issues, resulting in thorough cross-validation. A growing unit test suite validates complexity claims against actual Python behavior.
52+
This documentation has been reviewed and refined by multiple AI coding agents (Amp, Claude, Gemini CLI, Kiro, Copilot, Codex) and models (Opus 4.(5|6), Sonnet 4.5, Gemini 3 Pro, gpt-5.(2|3)-codex, ...) working alongside human contributors. Each agent brings different perspectives and catches different issues, resulting in thorough cross-validation. A growing unit test suite validates complexity claims against actual Python behavior.
5353

5454
It's also **fully open source**—anyone can review the content, [file issues](https://github.com/heikkitoivonen/python-time-space-complexity/issues), or [submit improvements](https://github.com/heikkitoivonen/python-time-space-complexity/pulls). All sources are cited, and claims are based on official Python documentation and CPython source code.
5555

docs/stdlib/array.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ lst = arr.tolist() # O(3)
8484

8585
# To bytes - O(n)
8686
bytes_data = arr.tobytes() # O(3)
87-
88-
# To string - O(n)
89-
str_data = arr.tostring() # O(3)
9087
```
9188

9289
## Performance Comparison

docs/stdlib/bisect.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ The `bisect` module provides binary search operations for sorted lists.
99
| `bisect_left(a, x)` | O(log n) | O(1) | Find leftmost position |
1010
| `bisect_right(a, x)` | O(log n) | O(1) | Find rightmost position |
1111
| `bisect(a, x)` | O(log n) | O(1) | Alias for bisect_right |
12-
| `insort_left(a, x)` | O(n) | O(n) | O(log n) search + O(n) insert |
13-
| `insort_right(a, x)` | O(n) | O(n) | O(log n) search + O(n) insert |
14-
| `insort(a, x)` | O(n) | O(n) | Alias for insort_right |
12+
| `insort_left(a, x)` | O(n) | O(1) | O(log n) search + O(n) insert (shifts elements in place) |
13+
| `insort_right(a, x)` | O(n) | O(1) | O(log n) search + O(n) insert (shifts elements in place) |
14+
| `insort(a, x)` | O(n) | O(1) | Alias for insort_right |
1515

1616
## Space Complexity
1717

1818
- Binary search operations: O(1) additional space
19-
- Insert operations: O(n) due to list shifting
19+
- Insert operations: O(1) additional space (shifts elements within the existing list)
2020

2121
## Implementation Details
2222

docs/stdlib/collections.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ from collections import ChainMap
222222
| `access[key]` | O(n) | O(1) | n = number of maps; searches until found |
223223
| `set[key]` | O(1) avg | O(1) | Sets in first map; O(m) worst case where m = first map size |
224224
| `del[key]` | O(1) avg | O(1) | Deletes from first map; O(m) worst case where m = first map size |
225-
| `len()` | O(n) | O(1) | Must check all maps |
225+
| `len()` | O(N) | O(N) | N = total keys across all maps; builds set union internally |
226226
| `in` | O(n) | O(1) | Checks all maps |
227227

228228
### Use Cases

docs/stdlib/graphlib.md

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -208,23 +208,25 @@ class BuildSystem:
208208
def build(self):
209209
"""Build all targets in order - O(v + e)"""
210210
self.sorter.prepare()
211-
211+
212212
built = set()
213-
while True:
214-
target = self.sorter.get_node()
215-
if target is None:
213+
while self.sorter.is_active():
214+
# get_ready() returns a tuple of ready nodes
215+
ready = self.sorter.get_ready()
216+
if not ready:
216217
break
217-
218-
# Skip already built
219-
if target in built:
218+
219+
for target in ready:
220+
# Skip already built
221+
if target in built:
222+
self.sorter.done(target)
223+
continue
224+
225+
print(f"Building {target}...")
226+
# Simulate build
227+
built.add(target)
220228
self.sorter.done(target)
221-
continue
222-
223-
print(f"Building {target}...")
224-
# Simulate build
225-
built.add(target)
226-
self.sorter.done(target)
227-
229+
228230
return built
229231

230232
# Usage
@@ -271,23 +273,24 @@ class TaskScheduler:
271273
executed = {}
272274
start_time = time.time()
273275

274-
while True:
275-
# Get next ready task - O(1) amortized
276-
task_name = self.sorter.get_node()
277-
if task_name is None:
276+
while self.sorter.is_active():
277+
# Get all ready tasks - O(1) amortized
278+
ready = self.sorter.get_ready()
279+
if not ready:
278280
break
279-
280-
# Execute task - O(?)
281-
if task_name in self.tasks:
282-
print(f"Executing {task_name}...")
283-
start = time.time()
284-
result = self.tasks[task_name]()
285-
elapsed = time.time() - start
286-
executed[task_name] = (result, elapsed)
287-
print(f" Completed in {elapsed:.3f}s")
288-
289-
# Mark done - O(d)
290-
self.sorter.done(task_name)
281+
282+
for task_name in ready:
283+
# Execute task - O(?)
284+
if task_name in self.tasks:
285+
print(f"Executing {task_name}...")
286+
start = time.time()
287+
result = self.tasks[task_name]()
288+
elapsed = time.time() - start
289+
executed[task_name] = (result, elapsed)
290+
print(f" Completed in {elapsed:.3f}s")
291+
292+
# Mark done - O(d)
293+
self.sorter.done(task_name)
291294

292295
total = time.time() - start_time
293296
print(f"Total execution time: {total:.3f}s")

0 commit comments

Comments
 (0)