Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@
* "product": 30 // 2 * 3 * 5
* }
*
* Time Complexity:
* Space Complexity:
* Optimal Time Complexity:
* Time Complexity: O(n) - We go through the list only once. The previous code had two loops (2n), but now we do everything in one loop (n).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though the performance is improved by combining the loops, the
complexity remains O(n); the constant factor is ignored in complexity analysis.

* Space Complexity: O(1) - We represent the result with just two variables (sum and product), so we don't use extra memory.
* Optimal Time Complexity: O(n) - We have to look at every number at least once, so we can't be faster than O(n).
*
* @param {Array<number>} numbers - Numbers to process
* @returns {Object} Object containing running total and product
*/
export function calculateSumAndProduct(numbers) {
let sum = 0;
for (const num of numbers) {
sum += num;
}

let product = 1;

// Refactor: Instead of looping twice, I calculate both sum and product in the same loop.
// This is better because we only loop through the list once.
for (const num of numbers) {
sum += num;
product *= num;
}

Expand Down
29 changes: 23 additions & 6 deletions Sprint-1/JavaScript/findCommonItems/findCommonItems.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
/**
* Finds common items between two arrays.
*
* Time Complexity:
* Space Complexity:
* Optimal Time Complexity:
* Time Complexity: O(n + m)
* The old code used .includes() inside .filter(), which meant a loop inside a loop (O(n^2)).
* By using a 'Set', we can check if an item exists instantly (O(1)).
*
* Space Complexity: O(n) - We create a Set to store the items from the first array.
*
* Optimal Time Complexity: O(n) - We must look at every item at least once to compare them.
*
* @param {Array} firstArray - First array to compare
* @param {Array} secondArray - Second array to compare
* @returns {Array} Array containing unique common items
*/
export const findCommonItems = (firstArray, secondArray) => [
...new Set(firstArray.filter((item) => secondArray.includes(item))),
];
export const findCommonItems = (firstArray, secondArray) => {
// Refactor: I put the first array into a Set for fast checking.
const itemsInFirst = new Set(firstArray);
const commonItems = new Set();

for (const item of secondArray) {
// Checking 'itemsInFirst.has(item)' is very fast O(1).
// The old 'includes()' was slow because it searched the whole list O(n).
if (itemsInFirst.has(item)) {
commonItems.add(item);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the complexity remains unchanged, appending an item to an array is typically faster than adding an item to a set.

}
}

// Convert the Set back to an array to return it
return [...commonItems];
};
30 changes: 22 additions & 8 deletions Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
/**
* Find if there is a pair of numbers that sum to a given target value.
*
* Time Complexity:
* Space Complexity:
* Optimal Time Complexity:
* Time Complexity: O(n)
* The old code used nested loops (loop inside a loop) which is slow O(n^2).
* I used a Set to remember the numbers we have seen. This lets us find the answer in one loop O(n).
*
* Space Complexity: O(n) - We use a Set to store the numbers we have visited.
* Optimal Time Complexity: O(n) - We need to check the numbers at least once to find the pair.
*
* @param {Array<number>} numbers - Array of numbers to search through
* @param {number} target - Target sum to find
* @returns {boolean} True if pair exists, false otherwise
*/
export function hasPairWithSum(numbers, target) {
for (let i = 0; i < numbers.length; i++) {
for (let j = i + 1; j < numbers.length; j++) {
if (numbers[i] + numbers[j] === target) {
return true;
}
// Refactor: I used a Set to store numbers we have already seen.
const seenNumbers = new Set();

for (const num of numbers) {
// Calculate what number we need to reach the target.
// Example: If target is 10 and num is 3, we need 7.
const match = target - num;

// Check if the number we need is already in our Set.
// .has() is very fast O(1).
if (seenNumbers.has(match)) {
return true;
}

// Add the current number to the Set so we can use it later.
seenNumbers.add(num);
}

return false;
}
36 changes: 9 additions & 27 deletions Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs
Original file line number Diff line number Diff line change
@@ -1,36 +1,18 @@
/**
* Remove duplicate values from a sequence, preserving the order of the first occurrence of each value.
*
* Time Complexity:
* Space Complexity:
* Optimal Time Complexity:
* Time Complexity: O(n)
* The old code used a nested loop (checking the result array for every item), which is O(n^2).
* A Set automatically removes duplicates in one go. Converting Array -> Set -> Array takes linear time O(n).
*
* Space Complexity: O(n) - We create a new Set/Array to store the unique items.
* Optimal Time Complexity: O(n) - We must look at every item at least once to see what it is.
*
* @param {Array} inputSequence - Sequence to remove duplicates from
* @returns {Array} New sequence with duplicates removed
*/
export function removeDuplicates(inputSequence) {
const uniqueItems = [];

for (
let currentIndex = 0;
currentIndex < inputSequence.length;
currentIndex++
) {
let isDuplicate = false;
for (
let compareIndex = 0;
compareIndex < uniqueItems.length;
compareIndex++
) {
if (inputSequence[currentIndex] === uniqueItems[compareIndex]) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
uniqueItems.push(inputSequence[currentIndex]);
}
}

return uniqueItems;
// Refactor: I used a Set to remove duplicates automatically.
// It creates a Set (removes duplicates) and spreads it back into an array.
return [...new Set(inputSequence)];
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ def calculate_sum_and_product(input_numbers: List[int]) -> Dict[str, int]:
"sum": 10, // 2 + 3 + 5
"product": 30 // 2 * 3 * 5
}
Time Complexity:
Space Complexity:
Optimal time complexity:
Time Complexity: O(n)
The previous code iterated through the list twice (2n).
I combined them into a single loop, so we iterate only once (n).

Space Complexity: O(1) - We only use two variables (running_sum and running_product) regardless of the list size.
Optimal time complexity: O(n) - We must visit every number at least once.
"""
# Edge case: empty list
if not input_numbers:
return {"sum": 0, "product": 1}

sum = 0
for current_number in input_numbers:
sum += current_number
running_sum = 0
running_product = 1

product = 1
for current_number in input_numbers:
product *= current_number
# Refactor: Calculate both sum and product in one loop.
for number in input_numbers:
running_sum += number
running_product *= number

return {"sum": sum, "product": product}
return {"sum": running_sum, "product": running_product}
19 changes: 10 additions & 9 deletions Sprint-1/Python/find_common_items/find_common_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ def find_common_items(
"""
Find common items between two arrays.

Time Complexity:
Space Complexity:
Optimal time complexity:
Time Complexity: O(n)
The old code used nested loops (loop inside a loop), which is slow O(n^2).
I converted the lists to Sets. Finding the intersection of two sets is linear time O(n).

Space Complexity: O(n) - We create a new set to store the items for comparison.
Optimal time complexity: O(n) - We must read the input lists at least once to compare them.
"""
common_items: List[ItemType] = []
for i in first_sequence:
for j in second_sequence:
if i == j and i not in common_items:
common_items.append(i)
return common_items

# Refactor: I used Python Sets.
# set(first_sequence) & set(second_sequence) finds common items instantly.
return list(set(first_sequence) & set(second_sequence))
27 changes: 20 additions & 7 deletions Sprint-1/Python/has_pair_with_sum/has_pair_with_sum.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,25 @@ def has_pair_with_sum(numbers: List[Number], target_sum: Number) -> bool:
"""
Find if there is a pair of numbers that sum to a target value.

Time Complexity:
Space Complexity:
Optimal time complexity:
Time Complexity: O(n)
The previous code used nested loops (loop inside a loop), which is slow O(n^2).
I used a Set to remember the numbers we have seen. This allows us to find the pair in one pass O(n).

Space Complexity: O(n) - We store the visited numbers in a Set.
Optimal time complexity: O(n) - We have to check each number at least once.
"""
for i in range(len(numbers)):
for j in range(i + 1, len(numbers)):
if numbers[i] + numbers[j] == target_sum:
return True
# Refactor: I used a Set to store numbers we have already seen.
seen_numbers = set()

for num in numbers:
# Calculate the number we need to reach the target.
match = target_sum - num

# Check if the needed number is already in our set.
if match in seen_numbers:
return True

# Add the current number to the set so we can use it later.
seen_numbers.add(num)

return False
23 changes: 14 additions & 9 deletions Sprint-1/Python/remove_duplicates/remove_duplicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,24 @@ def remove_duplicates(values: Sequence[ItemType]) -> List[ItemType]:
"""
Remove duplicate values from a sequence, preserving the order of the first occurrence of each value.

Time complexity:
Space complexity:
Optimal time complexity:
Time complexity: O(n)
The old code checked the list repeatedly, which is O(n^2).
I used a 'Set' to remember seen items for O(1) lookups, while appending to a list to keep the order.

Space Complexity: O(n) - We use a Set to store seen items and a List for the result.

Optimal time complexity: O(n) - We must iterate through the input at least once.
"""

# Refactor: I used a Set to track items we have seen because checking a Set is O(1).
# I also used a List to build the result so we keep the original order.
seen = set()
unique_items = []

for value in values:
is_duplicate = False
for existing in unique_items:
if value == existing:
is_duplicate = True
break
if not is_duplicate:
# Check if we have seen this value before.
if value not in seen:
unique_items.append(value)
seen.add(value)

return unique_items
Comment on lines +21 to 30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the approach you used in the JS version?