⚡️ Speed up function longest_increasing_subsequence_length by 40,778%
#1072
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 40,778% (407.78x) speedup for
longest_increasing_subsequence_lengthincode_to_optimize/sample_code.py⏱️ Runtime :
859 milliseconds→2.10 milliseconds(best of79runs)📝 Explanation and details
The optimized code achieves a 408x speedup by replacing the O(n²) dynamic programming algorithm with an O(n log n) patience sorting approach using binary search.
Key algorithmic change:
tailsarray wheretails[k]stores the smallest tail value of any increasing subsequence of lengthk+1. For each element, usesbisect.bisect_left()to find its insertion position in O(log n) time.Why this is faster:
bisectmodule is implemented in C and highly optimized for sorted list operations.tailslist grows incrementally and stays small (max length = LIS length, not input length).Performance characteristics from test results:
Impact considerations:
The optimization maintains identical correctness (handles integers, floats, negatives, duplicates, edge cases) while dramatically improving performance on any input size > ~10 elements. Given the massive speedup on realistic data sizes, this change would benefit any workload calling this function repeatedly or on non-trivial arrays.
✅ Correctness verification report:
⚙️ Click to see Existing Unit Tests
test_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_all_same_elementstest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_alternating_sequencetest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_classic_exampletest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_empty_arraytest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_float_valuestest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_longer_sequencetest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_negative_numberstest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_single_elementtest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_strictly_decreasingtest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_strictly_increasingtest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_two_elements_decreasingtest_numba_jit_code.py::TestLongestIncreasingSubsequenceLength.test_two_elements_increasing🌀 Click to see Generated Regression Tests
To edit these changes
git checkout codeflash/optimize-longest_increasing_subsequence_length-mkgfjtjcand push.