diff --git a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js index ce738c3..2a0e3b3 100644 --- a/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js +++ b/Sprint-1/JavaScript/calculateSumAndProduct/calculateSumAndProduct.js @@ -9,26 +9,21 @@ * "product": 30 // 2 * 3 * 5 * } * - * Time Complexity: - * Space Complexity: - * Optimal Time Complexity: + * Time Complexity:O(2n) originally have this as using 2 separate loops + * Space Complexity:O(1) no extra space used that rows with input + * Optimal Time Complexity:O(n) must at least visit each number once * * @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; + //only one loop needed to calculate both sum and product for (const num of numbers) { + sum += num; product *= num; } - return { - sum: sum, - product: product, - }; + return {sum, product}; } diff --git a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js index 5619ae5..08a21fb 100644 --- a/Sprint-1/JavaScript/findCommonItems/findCommonItems.js +++ b/Sprint-1/JavaScript/findCommonItems/findCommonItems.js @@ -1,14 +1,26 @@ /** * Finds common items between two arrays. * - * Time Complexity: - * Space Complexity: - * Optimal Time Complexity: + * Time Complexity:O(n+m) it build set and loop through arrays once + * Space Complexity: store second array in set + * Optimal Time Complexity:O(m+n) * * @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))), -]; + +// Refactored to use a Set for faster lookups, making the code more efficient +export const findCommonItems = (firstArray, secondArray) => { + const setB = new Set(secondArray); + const common = new Set(); + + for (const item of firstArray) { + if (setB.has(item)) { + common.add(item); + } + } + + return [...common]; +}; + diff --git a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js index dd2901f..27243db 100644 --- a/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js +++ b/Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js @@ -1,21 +1,25 @@ /** * 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(n2) the function use 2 nested loop + * Space Complexity:o(1)no additional significant memory used + * Optimal Time Complexity: O(n) — in the refactored version using a Set for lookups * * @param {Array} numbers - Array of numbers to search through * @param {number} target - Target sum to find * @returns {boolean} True if pair exists, false otherwise */ +//The original version used two nested loops, meaning it checked every possible pair of numbers in the array to see if they added up to the target. This approach has a time complexity of O(n²), which becomes very slow as the list grows larger. 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 seen = new Set(); + + for (const num of numbers) { + const complement = target - num; + if (seen.has(complement)) { + return true; } + seen.add(num); } + return false; } diff --git a/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs b/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs index dc5f771..6b0a7e4 100644 --- a/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs +++ b/Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs @@ -1,34 +1,21 @@ /** * 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 function iterates through the input sequence once + * Space Complexity: O(n) — in the worst case, all elements are unique and stored in the Set and output array + * Optimal Time Complexity: O(n) — must at least visit each element once * * @param {Array} inputSequence - Sequence to remove duplicates from * @returns {Array} New sequence with duplicates removed */ export function removeDuplicates(inputSequence) { + const seen = new Set(); 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]); + for (const item of inputSequence) { + if (!seen.has(item)) { + seen.add(item); + uniqueItems.push(item); } } diff --git a/Sprint-2/implement_linked_list/linked_list.py b/Sprint-2/implement_linked_list/linked_list.py index e69de29..7a7820f 100644 --- a/Sprint-2/implement_linked_list/linked_list.py +++ b/Sprint-2/implement_linked_list/linked_list.py @@ -0,0 +1,50 @@ +class Node: + def __init__(self, value): + self.value = value + self.previous = None # renamed from prev + self.next = None + + +class LinkedList: + def __init__(self): + self.head = None + self.tail = None + + def push_head(self, value): + """Add element to start (O(1))""" + new_node = Node(value) + new_node.next = self.head + + if self.head: + self.head.previous = new_node + else: + # If list was empty, tail is also the new node + self.tail = new_node + + self.head = new_node + return new_node # handle for later removal + + def pop_tail(self): + """Remove element from end (O(1))""" + if not self.tail: + raise IndexError("pop_tail from empty list") + + value = self.tail.value + self.remove(self.tail) + return value + + def remove(self, node): + """Remove node (O(1)) using the handle""" + if node.previous: + node.previous.next = node.next + else: + # Node is head + self.head = node.next + + if node.next: + node.next.previous = node.previous + else: + # Node is tail + self.tail = node.previous + + node.previous = node.next = None