From b3c3ec12c3138a984736ac67fce096ffd0d399a9 Mon Sep 17 00:00:00 2001 From: shreefAhmedM Date: Mon, 12 Oct 2026 13:36:36 +0100 Subject: [PATCH 1/5] analyse and refactor sprint functions --- .../calculateSumAndProduct.js | 10 ++--- .../findCommonItems/findCommonItems.js | 21 +++++++++-- .../hasPairWithSum/hasPairWithSum.js | 19 +++++++--- .../removeDuplicates/removeDuplicates.mjs | 37 ++++++++----------- 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js index ce738c33..f88927cc 100644 --- a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js +++ b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js @@ -18,17 +18,13 @@ */ export function calculateSumAndProduct(numbers) { let sum = 0; + let product =1 for (const num of numbers) { sum += num; + product *= num } - - let product = 1; - for (const num of numbers) { - product *= num; - } - return { sum: sum, product: product, }; -} +} \ No newline at end of file diff --git a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js index 5619ae5d..da5ee947 100644 --- a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js +++ b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js @@ -8,7 +8,22 @@ * @param {Array} firstArray - First array to compare * @param {Array} secondArray - Second array to compare * @returns {Array} Array containing unique common items + * + * Time Complexity: O(n * m) + * Space Complexity: O(u) + * Optimal Time Complexity: O(n + m) */ -export const findCommonItems = (firstArray, secondArray) => [ - ...new Set(firstArray.filter((item) => secondArray.includes(item))), -]; +export const findCommonItems = (firstArray, secondArray) => { + const allowedItems = new Set(secondArray); + + const uniqueValues = [ + ...new Set(firstArray.filter((item) => allowedItems.has(item))), + ]; + return uniqueValues; +}; + +console.log(findCommonItems([2, 5, 7], [5, 6, 7])); + +// Time:O(n \ m) filter() visits each item in the first array, and includes() may scan the second array each time. +// Sace: O(k) The Set stores unique common items, and the resulting array contains those items. +// Optimal time: O(n+m) Achievable on average using a Set for efficient lookups. \ No newline at end of file diff --git a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js index dd2901f6..0cde9e5b 100644 --- a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js +++ b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js @@ -4,18 +4,25 @@ * Time Complexity: * Space Complexity: * Optimal Time Complexity: + * + * Time Complexity: O(N^2) +// Space Complexity: O(1) +// Optimal Time Complexity: O(N) * * @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; - } - } + const seenNumbers = new Set(); + + for (const currentNumber of numbers) { + const complement = target - currentNumber; + + if (seenNumbers.has(complement)) return true; + + seenNumbers.add(currentNumber); } return false; + } diff --git a/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs b/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs index dc5f7711..ec062422 100644 --- a/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs +++ b/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs @@ -9,28 +9,21 @@ * @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 [...new Set(inputSequence)] - return uniqueItems; } +// Original complexity: +// The original approach typically uses nested loops to compare +// each value with the remaining values in the sequence. +// This results in O(n²) time complexity because each value +// may be compared with every other value. + + +// Refactor: +// Use a Set to remove duplicate values while preserving the +// order of their first occurrence. +// The Set stores only unique values, and spreading the Set +// into a new array creates the result. +// Set insertion is O(1) on average, so processing all n +// elements takes O(n) time overall. \ No newline at end of file From 3418034fa23dfa6f20245d000a134a38519da54e Mon Sep 17 00:00:00 2001 From: shreefAhmedM Date: Tue, 13 Oct 2026 19:28:14 +0100 Subject: [PATCH 2/5] Implement a linked list data structure in Python --- Sprint-2/implement_linked_list/linked_list.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index e69de29b..532080a5 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -0,0 +1,79 @@ +class Node: + """A private node structure that serves as the 'handle' for O(1) removal.""" + def __init__(self, value): + self.value = value + self.next = None + self.previous = None + + +class LinkedList: + def __init__(self): + self.head = None + self.tail = None + + def push_head(self, item): + """Adds an element to the start of the list. Returns the Node handle.""" + new_node = Node(item) + + if not self.head: + # If the list is empty, both head and tail point to the new node + self.head = new_node + self.tail = new_node + else: + # Insert at the beginning + new_node.next = self.head + self.head.previous = new_node + self.head = new_node + + return new_node + + def pop_tail(self): + """Removes and returns the element value from the end of the list.""" + if not self.tail: + return None # Or raise IndexError depending on preference + + popped_node = self.tail + value = popped_node.value + + if self.head == self.tail: + # Only one element in the list + self.head = None + self.tail = None + else: + # Move tail back and sever the link + self.tail = self.tail.previous + self.tail.next = None + + # Clean up pointers of the removed node + popped_node.previous = None + return value + + def remove(self, node: Node): + """Removes a specific node directly using its handle in O(1) time.""" + if not node: + return + + # Case 1: Node is the head + if node == self.head: + self.head = node.next + if self.head: + self.head.previous = None + else: + self.tail = None # List is now empty + + # Case 2: Node is the tail + elif node == self.tail: + self.tail = node.previous + if self.tail: + self.tail.next = None + else: + self.head = None # List is now empty + + # Case 3: Node is in the middle + else: + node.previous.next = node.next + node.next.previous = node.previous + + # Completely isolate the removed node + node.next = None + node.previous = None From 38449aaf2d37fa122f06d9c38e68752cf63af139 Mon Sep 17 00:00:00 2001 From: shreefAhmedM Date: Fri, 16 Oct 2026 16:33:28 +0100 Subject: [PATCH 3/5] refactoring calculateSumAndProduct file --- .../calculateSumAndProduct.js | 15 ++++++--- .../making_change/making_change.py | 32 ------------------- 2 files changed, 10 insertions(+), 37 deletions(-) diff --git a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js index f88927cc..2009f220 100644 --- a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js +++ b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js @@ -9,16 +9,16 @@ * "product": 30 // 2 * 3 * 5 * } * - * Time Complexity: - * Space Complexity: - * Optimal Time Complexity: + * Time Complexity: O(n) + * Space Complexity: O(1) + * Optimal Time Complexity: O(n) * * @param {Array} numbers - Numbers to process * @returns {Object} Object containing running total and product */ export function calculateSumAndProduct(numbers) { let sum = 0; - let product =1 + let product = 1; for (const num of numbers) { sum += num; product *= num @@ -27,4 +27,9 @@ export function calculateSumAndProduct(numbers) { sum: sum, product: product, }; -} \ No newline at end of file +} +//Time Complexity: O(n) The loop visits each element exactly once +// Space complexity is O(1) he function uses a fixed number of variables, regardless of the input size. +// The returned object also has a fixed size. +// Optimal time complexity is O(n) because every element must be examined +// to guarantee the correct sum and product. \ No newline at end of file diff --git a/Sprint-2/improve_with_caches/making_change/making_change.py b/Sprint-2/improve_with_caches/making_change/making_change.py index 255612e5..e69de29b 100644 --- a/Sprint-2/improve_with_caches/making_change/making_change.py +++ b/Sprint-2/improve_with_caches/making_change/making_change.py @@ -1,32 +0,0 @@ -from typing import List - - -def ways_to_make_change(total: int) -> int: - """ - Given access to coins with the values 1, 2, 5, 10, 20, 50, 100, 200, returns a count of all of the ways to make the passed total value. - - For instance, there are two ways to make a value of 3: with 3x 1 coins, or with 1x 1 coin and 1x 2 coin. - """ - return ways_to_make_change_helper(total, [200, 100, 50, 20, 10, 5, 2, 1]) - - -def ways_to_make_change_helper(total: int, coins: List[int]) -> int: - """ - Helper function for ways_to_make_change to avoid exposing the coins parameter to callers. - """ - if total == 0 or len(coins) == 0: - return 0 - - ways = 0 - for coin_index in range(len(coins)): - coin = coins[coin_index] - count_of_coin = 1 - while coin * count_of_coin <= total: - total_from_coins = coin * count_of_coin - if total_from_coins == total: - ways += 1 - else: - intermediate = ways_to_make_change_helper(total - total_from_coins, coins=coins[coin_index+1:]) - ways += intermediate - count_of_coin += 1 - return ways From 7928c486168de9ac9a519d5425926b6af0895a5d Mon Sep 17 00:00:00 2001 From: shreefAhmedM Date: Sat, 17 Oct 2026 13:20:00 +0100 Subject: [PATCH 4/5] Remove unrelated Sprint-2 changes from PR --- Sprint-2/implement_linked_list/linked_list.py | 79 ------------------- .../making_change/making_change.py | 32 ++++++++ 2 files changed, 32 insertions(+), 79 deletions(-) diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index 532080a5..e69de29b 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -1,79 +0,0 @@ -class Node: - """A private node structure that serves as the 'handle' for O(1) removal.""" - def __init__(self, value): - self.value = value - self.next = None - self.previous = None - - -class LinkedList: - def __init__(self): - self.head = None - self.tail = None - - def push_head(self, item): - """Adds an element to the start of the list. Returns the Node handle.""" - new_node = Node(item) - - if not self.head: - # If the list is empty, both head and tail point to the new node - self.head = new_node - self.tail = new_node - else: - # Insert at the beginning - new_node.next = self.head - self.head.previous = new_node - self.head = new_node - - return new_node - - def pop_tail(self): - """Removes and returns the element value from the end of the list.""" - if not self.tail: - return None # Or raise IndexError depending on preference - - popped_node = self.tail - value = popped_node.value - - if self.head == self.tail: - # Only one element in the list - self.head = None - self.tail = None - else: - # Move tail back and sever the link - self.tail = self.tail.previous - self.tail.next = None - - # Clean up pointers of the removed node - popped_node.previous = None - return value - - def remove(self, node: Node): - """Removes a specific node directly using its handle in O(1) time.""" - if not node: - return - - # Case 1: Node is the head - if node == self.head: - self.head = node.next - if self.head: - self.head.previous = None - else: - self.tail = None # List is now empty - - # Case 2: Node is the tail - elif node == self.tail: - self.tail = node.previous - if self.tail: - self.tail.next = None - else: - self.head = None # List is now empty - - # Case 3: Node is in the middle - else: - node.previous.next = node.next - node.next.previous = node.previous - - # Completely isolate the removed node - node.next = None - node.previous = None diff --git a/Sprint-2/improve_with_caches/making_change/making_change.py b/Sprint-2/improve_with_caches/making_change/making_change.py index e69de29b..255612e5 100644 --- a/Sprint-2/improve_with_caches/making_change/making_change.py +++ b/Sprint-2/improve_with_caches/making_change/making_change.py @@ -0,0 +1,32 @@ +from typing import List + + +def ways_to_make_change(total: int) -> int: + """ + Given access to coins with the values 1, 2, 5, 10, 20, 50, 100, 200, returns a count of all of the ways to make the passed total value. + + For instance, there are two ways to make a value of 3: with 3x 1 coins, or with 1x 1 coin and 1x 2 coin. + """ + return ways_to_make_change_helper(total, [200, 100, 50, 20, 10, 5, 2, 1]) + + +def ways_to_make_change_helper(total: int, coins: List[int]) -> int: + """ + Helper function for ways_to_make_change to avoid exposing the coins parameter to callers. + """ + if total == 0 or len(coins) == 0: + return 0 + + ways = 0 + for coin_index in range(len(coins)): + coin = coins[coin_index] + count_of_coin = 1 + while coin * count_of_coin <= total: + total_from_coins = coin * count_of_coin + if total_from_coins == total: + ways += 1 + else: + intermediate = ways_to_make_change_helper(total - total_from_coins, coins=coins[coin_index+1:]) + ways += intermediate + count_of_coin += 1 + return ways From ca928dfdd38ea4785bfa19b7d3b726982809afab Mon Sep 17 00:00:00 2001 From: shreefAhmedM Date: Sat, 17 Oct 2026 15:06:13 +0100 Subject: [PATCH 5/5] Optimize hasPairWithSum using a Set --- .../findCommonItems/findCommonItems.js | 25 +++++++++++-------- .../hasPairWithSum/hasPairWithSum.js | 4 +++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js index da5ee947..e4fcd4ce 100644 --- a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js +++ b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js @@ -1,17 +1,13 @@ /** * Finds common items between two arrays. - * - * Time Complexity: - * Space Complexity: - * Optimal Time Complexity: + * + * Time Complexity: O(n * m) + * Space Complexity: O(n) + * Optimal Time Complexity: O(n + m) * * @param {Array} firstArray - First array to compare * @param {Array} secondArray - Second array to compare * @returns {Array} Array containing unique common items - * - * Time Complexity: O(n * m) - * Space Complexity: O(u) - * Optimal Time Complexity: O(n + m) */ export const findCommonItems = (firstArray, secondArray) => { const allowedItems = new Set(secondArray); @@ -24,6 +20,13 @@ export const findCommonItems = (firstArray, secondArray) => { console.log(findCommonItems([2, 5, 7], [5, 6, 7])); -// Time:O(n \ m) filter() visits each item in the first array, and includes() may scan the second array each time. -// Sace: O(k) The Set stores unique common items, and the resulting array contains those items. -// Optimal time: O(n+m) Achievable on average using a Set for efficient lookups. \ No newline at end of file + +// Time Complexity: O(n + m) on average. +// Building the Set takes O(m), and filtering the first array takes O(n) +// on average because Set.has() provides efficient lookups. + +// Space Complexity: O(n + m). +// The Set stores elements from secondArray, while the filter result +// and the Set of unique common items require additional space. + +// Improvement: Reduces average time complexity from O(n * m) to O(n + m). \ No newline at end of file diff --git a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js index 0cde9e5b..01b4ff87 100644 --- a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js +++ b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js @@ -26,3 +26,7 @@ export function hasPairWithSum(numbers, target) { return false; } + + +// Time Complexity: O(n) We check each number once. +// Space Complexity: O(n) The Set may store all n numbers. \ No newline at end of file