diff --git a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js index ce738c3..5cd5a3c 100644 --- a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js +++ b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js @@ -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). + * 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} 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; } diff --git a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js index 5619ae5..bbc5fed 100644 --- a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js +++ b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js @@ -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); + } + } + + // Convert the Set back to an array to return it + return [...commonItems]; +}; \ No newline at end of file diff --git a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js index dd2901f..9e89abb 100644 --- a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js +++ b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js @@ -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} 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; } diff --git a/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs b/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs index dc5f771..516086d 100644 --- a/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs +++ b/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs @@ -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)]; } diff --git a/Sprint-1/Python/calculate_sum_and_product/calculate_sum_and_product.py b/Sprint-1/Python/calculate_sum_and_product/calculate_sum_and_product.py index cfd5cfd..cbbfefe 100644 --- a/Sprint-1/Python/calculate_sum_and_product/calculate_sum_and_product.py +++ b/Sprint-1/Python/calculate_sum_and_product/calculate_sum_and_product.py @@ -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} diff --git a/Sprint-1/Python/find_common_items/find_common_items.py b/Sprint-1/Python/find_common_items/find_common_items.py index 478e2ef..a42a377 100644 --- a/Sprint-1/Python/find_common_items/find_common_items.py +++ b/Sprint-1/Python/find_common_items/find_common_items.py @@ -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)) diff --git a/Sprint-1/Python/has_pair_with_sum/has_pair_with_sum.py b/Sprint-1/Python/has_pair_with_sum/has_pair_with_sum.py index fe2da51..0850d3d 100644 --- a/Sprint-1/Python/has_pair_with_sum/has_pair_with_sum.py +++ b/Sprint-1/Python/has_pair_with_sum/has_pair_with_sum.py @@ -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 diff --git a/Sprint-1/Python/remove_duplicates/remove_duplicates.py b/Sprint-1/Python/remove_duplicates/remove_duplicates.py index c9fdbe8..7a19007 100644 --- a/Sprint-1/Python/remove_duplicates/remove_duplicates.py +++ b/Sprint-1/Python/remove_duplicates/remove_duplicates.py @@ -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