Skip to content

Commit 2697d35

Browse files
committed
perf(js): optimize calculateSumAndProduct (2n → n)
1 parent 4f74f0c commit 2697d35

File tree

7 files changed

+296
-61
lines changed

7 files changed

+296
-61
lines changed
Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,46 @@
11
/**
22
* Finds common items between two arrays.
33
*
4-
* Time Complexity:
5-
* Space Complexity:
6-
* Optimal Time Complexity:
4+
* Time Complexity: O(n + m) - Single pass through both arrays
5+
* Space Complexity: O(min(n, m)) - Set size bounded by smaller array
6+
* Optimal Time Complexity: O(n + m) - Cannot do better than linear time
77
*
88
* @param {Array} firstArray - First array to compare
99
* @param {Array} secondArray - Second array to compare
1010
* @returns {Array} Array containing unique common items
1111
*/
12-
export const findCommonItems = (firstArray, secondArray) => [
13-
...new Set(firstArray.filter((item) => secondArray.includes(item))),
14-
];
12+
export const findCommonItems = (firstArray, secondArray) => {
13+
// OPTIMIZED IMPLEMENTATION: O(n + m) time complexity
14+
// Previous implementation: O(n × m) due to nested includes() calls
15+
16+
// Convert second array to Set for O(1) lookup: O(m) time, O(m) space
17+
const secondSet = new Set(secondArray);
18+
19+
// Find common items using Set lookup: O(n) time
20+
const commonItems = firstArray.filter((item) => secondSet.has(item));
21+
22+
// Remove duplicates: O(n) time in worst case
23+
return [...new Set(commonItems)];
24+
};
25+
26+
/*
27+
* ORIGINAL IMPLEMENTATION (for comparison):
28+
*
29+
* export const findCommonItems = (firstArray, secondArray) => [
30+
* ...new Set(firstArray.filter((item) => secondArray.includes(item))),
31+
* ];
32+
*
33+
* COMPLEXITY ANALYSIS OF ORIGINAL:
34+
* - firstArray.filter(): O(n) iterations
35+
* - secondArray.includes(): O(m) for each iteration
36+
* - Total: O(n × m) time complexity
37+
* - Space: O(n) for Set creation
38+
*
39+
40+
* IMPROVEMENTS MADE:
41+
* 1. Reduced from O(n × m) to O(n + m) time complexity
42+
* 2. Set lookup is O(1) vs Array.includes() O(m)
43+
* 3. Significant performance gain for large arrays
44+
* 4. Same functionality with better algorithmic efficiency
45+
46+
*/
Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,59 @@
11
/**
22
* Find if there is a pair of numbers that sum to a given target value.
33
*
4-
* Time Complexity:
5-
* Space Complexity:
6-
* Optimal Time Complexity:
4+
* Time Complexity: O(n) - Single pass through the array
5+
* Space Complexity: O(n) - Set to store seen numbers
6+
* Optimal Time Complexity: O(n) - Cannot do better than linear time
77
*
88
* @param {Array<number>} numbers - Array of numbers to search through
99
* @param {number} target - Target sum to find
1010
* @returns {boolean} True if pair exists, false otherwise
1111
*/
1212
export function hasPairWithSum(numbers, target) {
13-
for (let i = 0; i < numbers.length; i++) {
14-
for (let j = i + 1; j < numbers.length; j++) {
15-
if (numbers[i] + numbers[j] === target) {
16-
return true;
17-
}
13+
// OPTIMIZED IMPLEMENTATION: O(n) time complexity
14+
// Previous implementation: O(n²) due to nested loops
15+
16+
const seen = new Set(); // O(n)
17+
18+
// O(n) time complexity
19+
for (const num of numbers) {
20+
const complement = target - num;
21+
// O(1) lookup
22+
if (seen.has(complement)) {
23+
return true;
1824
}
25+
26+
// O(1) operation
27+
seen.add(num);
1928
}
2029
return false;
2130
}
31+
console.log(hasPairWithSum([3, 2, 3, 4, 5], 9));
32+
/*
33+
* ORIGINAL IMPLEMENTATION (for comparison):
34+
*
35+
* export function hasPairWithSum(numbers, target) {
36+
* for (let i = 0; i < numbers.length; i++) { // O(n) iterations
37+
* for (let j = i + 1; j < numbers.length; j++) { // O(n) iterations each
38+
* if (numbers[i] + numbers[j] === target) { // O(1) comparison
39+
* return true;
40+
* }
41+
* }
42+
* }
43+
* return false;
44+
* }
45+
*
46+
* COMPLEXITY ANALYSIS OF ORIGINAL:
47+
* - Outer loop: O(n) iterations
48+
* - Inner loop: O(n) iterations for each outer iteration
49+
* - Total: O(n²) time complexity
50+
* - Space: O(1) - only using loop variables
51+
*
52+
* PERFORMANCE ISSUES:
53+
* - Quadratic time complexity O(n²)
54+
*
55+
* IMPROVEMENTS MADE:
56+
* 1. Reduced from O(n²) to O(n) time complexity
57+
* 2. Single pass through array instead of nested loops
58+
* 3. Set lookup is O(1) vs nested iteration O(n)
59+
*/
Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,65 @@
11
/**
22
* Remove duplicate values from a sequence, preserving the order of the first occurrence of each value.
33
*
4-
* Time Complexity:
5-
* Space Complexity:
6-
* Optimal Time Complexity:
4+
* Time Complexity: O(n) - Single pass through the array
5+
* Space Complexity: O(n) - Set to track seen elements
6+
* Optimal Time Complexity: O(n) - Cannot do better than linear time
77
*
88
* @param {Array} inputSequence - Sequence to remove duplicates from
99
* @returns {Array} New sequence with duplicates removed
1010
*/
1111
export function removeDuplicates(inputSequence) {
12-
const uniqueItems = [];
12+
// OPTIMIZED IMPLEMENTATION: O(n) time complexity
13+
// Previous implementation: O(n²) due to nested loops checking each element
1314

14-
for (
15-
let currentIndex = 0;
16-
currentIndex < inputSequence.length;
17-
currentIndex++
18-
) {
19-
let isDuplicate = false;
20-
for (
21-
let compareIndex = 0;
22-
compareIndex < uniqueItems.length;
23-
compareIndex++
24-
) {
25-
if (inputSequence[currentIndex] === uniqueItems[compareIndex]) {
26-
isDuplicate = true;
27-
break;
28-
}
29-
}
30-
if (!isDuplicate) {
31-
uniqueItems.push(inputSequence[currentIndex]);
15+
const seen = new Set(); // O(n)
16+
const uniqueItems = []; // O(n)
17+
18+
// O(n) time complexity
19+
for (const item of inputSequence) {
20+
// O(1) lookup
21+
if (!seen.has(item)) {
22+
seen.add(item); // O(1) operation
23+
uniqueItems.push(item); // O(1) operation
3224
}
3325
}
3426

3527
return uniqueItems;
3628
}
29+
console.log(removeDuplicates([1, 2, 3, 4, 5, 1, 2, 3, 4, 5]));
30+
/*
31+
* ORIGINAL IMPLEMENTATION (for comparison):
32+
*
33+
* export function removeDuplicates(inputSequence) {
34+
* const uniqueItems = [];
35+
*
36+
* for (let currentIndex = 0; currentIndex < inputSequence.length; currentIndex++) {
37+
* let isDuplicate = false;
38+
* for (let compareIndex = 0; compareIndex < uniqueItems.length; compareIndex++) {
39+
* if (inputSequence[currentIndex] === uniqueItems[compareIndex]) {
40+
* isDuplicate = true;
41+
* break;
42+
* }
43+
* }
44+
* if (!isDuplicate) {
45+
* uniqueItems.push(inputSequence[currentIndex]);
46+
* }
47+
* }
48+
*
49+
* return uniqueItems;
50+
* }
51+
*
52+
* COMPLEXITY ANALYSIS OF ORIGINAL:
53+
* - Outer loop: O(n) iterations through input array
54+
* - Inner loop: O(k) iterations through uniqueItems array (k grows with each unique element)
55+
* - Worst case: O(n²) when all elements are unique
56+
* - Space: O(n) for uniqueItems array
57+
*
58+
* PERFORMANCE ISSUES:
59+
* - Quadratic time complexity O(n²) in worst case
60+
*
61+
* IMPROVEMENTS MADE:
62+
* 1. Reduced from O(n²) to O(n) time complexity
63+
* 2. Set lookup is O(1) vs linear search O(k)
64+
* 3. Single pass through input array
65+
*/

Sprint-1/Python/calculate_sum_and_product/calculate_sum_and_product.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,50 @@ def calculate_sum_and_product(input_numbers: List[int]) -> Dict[str, int]:
1212
"sum": 10, // 2 + 3 + 5
1313
"product": 30 // 2 * 3 * 5
1414
}
15-
Time Complexity:
16-
Space Complexity:
17-
Optimal time complexity:
15+
16+
Time Complexity: O(n) - Single pass through the list
17+
Space Complexity: O(1) - Only using constant extra space
18+
Optimal Time Complexity: O(n) - Cannot do better than linear time
1819
"""
20+
# OPTIMIZED IMPLEMENTATION: O(n) time complexity
21+
# Previous implementation: O(2n) due to two separate loops
22+
23+
sum_total = 0 # O(1) space
24+
product = 1 # O(1) space
25+
26+
# O(n) time complexity
27+
for current_number in input_numbers:
28+
sum_total += current_number # O(1)
29+
product *= current_number # O(1)
30+
31+
return {"sum": sum_total, "product": product}
32+
33+
34+
# ORIGINAL IMPLEMENTATION (for comparison):
35+
"""
36+
def calculate_sum_and_product(input_numbers: List[int]) -> Dict[str, int]:
1937
# Edge case: empty list
2038
if not input_numbers:
2139
return {"sum": 0, "product": 1}
2240
2341
sum = 0
24-
for current_number in input_numbers:
42+
for current_number in input_numbers: # First pass: O(n)
2543
sum += current_number
2644
2745
product = 1
28-
for current_number in input_numbers:
46+
for current_number in input_numbers: # Second pass: O(n)
2947
product *= current_number
3048
31-
return {"sum": sum, "product": product}
49+
return {"sum": sum, "product": product} # Total: O(2n) = O(n) time
50+
51+
COMPLEXITY ANALYSIS OF ORIGINAL:
52+
- First loop: O(n) iterations to calculate sum
53+
- Second loop: O(n) iterations to calculate product
54+
- Total: O(2n) = O(n) time complexity
55+
- Space: O(1) - only using loop variables
56+
57+
IMPROVEMENTS MADE:
58+
1. Reduced from 2n to n operations (50% fewer iterations)
59+
2. Single pass through list instead of two separate loops
60+
3. Same O(n) time complexity but with better constant factors
61+
"""

Sprint-1/Python/find_common_items/find_common_items.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,49 @@ def find_common_items(
99
"""
1010
Find common items between two arrays.
1111
12-
Time Complexity:
13-
Space Complexity:
14-
Optimal time complexity:
12+
Time Complexity: O(n + m) - Single pass through both sequences
13+
Space Complexity: O(min(n, m)) - Set size bounded by smaller sequence
14+
Optimal Time Complexity: O(n + m) - Cannot do better than linear time
1515
"""
16+
# OPTIMIZED IMPLEMENTATION: O(n + m) time complexity
17+
# Previous implementation: O(n × m) due to nested loops with linear search
18+
19+
# Convert second sequence to set for O(1) lookup: O(m) time, O(m) space
20+
second_set = set(second_sequence)
21+
22+
# Find common items using set lookup: O(n) time
23+
common_items = []
24+
for item in first_sequence:
25+
if item in second_set and item not in common_items:
26+
common_items.append(item)
27+
28+
return common_items
29+
30+
31+
# ORIGINAL IMPLEMENTATION (for comparison):
32+
"""
33+
def find_common_items(
34+
first_sequence: Sequence[ItemType], second_sequence: Sequence[ItemType]
35+
) -> List[ItemType]:
1636
common_items: List[ItemType] = []
17-
for i in first_sequence:
18-
for j in second_sequence:
19-
if i == j and i not in common_items:
37+
for i in first_sequence: # O(n) iterations
38+
for j in second_sequence: # O(m) iterations each
39+
if i == j and i not in common_items: # O(k) linear search
2040
common_items.append(i)
2141
return common_items
42+
43+
COMPLEXITY ANALYSIS OF ORIGINAL:
44+
- Outer loop: O(n) iterations through first_sequence
45+
- Inner loop: O(m) iterations through second_sequence
46+
- Linear search: O(k) for 'i not in common_items' check
47+
- Total: O(n × m × k) time complexity in worst case
48+
- Space: O(n) for common_items list
49+
50+
PERFORMANCE ISSUES:
51+
- Quadratic time complexity O(n × m) from nested loops
52+
53+
IMPROVEMENTS MADE:
54+
1. Reduced from O(n × m × k) to O(n + m) time complexity
55+
2. Set lookup is O(1) vs nested iteration O(m)
56+
3. Single pass through first_sequence
57+
"""

Sprint-1/Python/has_pair_with_sum/has_pair_with_sum.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,48 @@ def has_pair_with_sum(numbers: List[Number], target_sum: Number) -> bool:
77
"""
88
Find if there is a pair of numbers that sum to a target value.
99
10-
Time Complexity:
11-
Space Complexity:
12-
Optimal time complexity:
10+
Time Complexity: O(n) - Single pass through the list
11+
Space Complexity: O(n) - Set to store seen numbers
12+
Optimal Time Complexity: O(n) - Cannot do better than linear time
1313
"""
14-
for i in range(len(numbers)):
15-
for j in range(i + 1, len(numbers)):
16-
if numbers[i] + numbers[j] == target_sum:
14+
# OPTIMIZED IMPLEMENTATION: O(n) time complexity
15+
# Previous implementation: O(n²) due to nested loops
16+
17+
seen = set() # O(n) space for storing seen numbers
18+
19+
# Single pass through list: O(n) time complexity
20+
for num in numbers:
21+
complement = target_sum - num
22+
23+
# Check if complement exists in seen numbers: O(1) lookup
24+
if complement in seen:
25+
return True
26+
27+
# Add current number to seen set: O(1) operation
28+
seen.add(num)
29+
30+
return False
31+
32+
# ORIGINAL IMPLEMENTATION (for comparison):
33+
"""
34+
def has_pair_with_sum(numbers: List[Number], target_sum: Number) -> bool:
35+
for i in range(len(numbers)): # O(n) iterations
36+
for j in range(i + 1, len(numbers)): # O(n) iterations each
37+
if numbers[i] + numbers[j] == target_sum: # O(1) comparison
1738
return True
1839
return False
40+
41+
COMPLEXITY ANALYSIS OF ORIGINAL:
42+
- Outer loop: O(n) iterations
43+
- Inner loop: O(n) iterations for each outer iteration
44+
- Total: O(n²) time complexity
45+
- Space: O(1) - only using loop variables
46+
47+
PERFORMANCE ISSUES:
48+
- Quadratic time complexity O(n²)
49+
50+
IMPROVEMENTS MADE:
51+
1. Reduced from O(n²) to O(n) time complexity
52+
2. Single pass through list instead of nested loops
53+
3. Set lookup is O(1) vs nested iteration O(n)
54+
"""

0 commit comments

Comments
 (0)