Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@
* "product": 30 // 2 * 3 * 5
* }
*
* Time Complexity:
* Space Complexity:
* Optimal Time Complexity:
* Time Complexity: O(n) the previous solution iterates through the lists twice, once for the sum and once for the product, but this solution iterates through the list only once, calculating both the sum and product in a single pass.



* Space Complexity: O(1) the space complexity is constant because we are using only a fixed amount of space to store the sum and product, regardless of the size of the input list.

* Optimal Time Complexity: O(n) because we need to iterate through all the numbers in the list at least once to calculate the sum and product. so even though the performance improves by reducing the number of iterations, the overall time complexity remains O(n) since we still need to process each element in the list.
*
* @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;

for (const num of numbers) {
sum += num;
product *= num;
}

Expand Down
23 changes: 17 additions & 6 deletions Sprint-1/JavaScript/findCommonItems/findCommonItems.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
/**
* Finds common items between two arrays.
*
* Time Complexity:
* Space Complexity:
* Optimal Time Complexity:
* Time Complexity: O(n + m) where n is the length of the first array and m is the length of the second array. This is because we create a Set from the second array (which takes O(m) time) and then filter the first array (which takes O(n) time). The overall time complexity is linear.



* Space Complexity: O(m) where m is the length of the second array. This is because we create a Set from the second array, which requires additional space The space complexity is linear with respect to the size of the second array.


* Optimal Time Complexity: O(n + m) because we need to process each element in both arrays at least once to find the common items. The use of a Set allows us to achieve this optimal time complexity.
*
* @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) => {
const bSet = new Set(secondArray);
return firstArray.filter((e) => bSet.has(e));
}

const arr1 = [2, 3, 5];
const arr2 = [1, 2, 3];
const commonItems = findCommonItems(arr1, arr2);
console.log(commonItems);
31 changes: 21 additions & 10 deletions Sprint-1/JavaScript/hasPairWithSum/hasPairWithSum.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
/**
* 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) where n is the length of the input array. This is because we iterate through the array once to check for pairs, and each lookup in the Set is O(1) on average. The overall time complexity is linear.
*
*
*
* Space Complexity: O(n) in the worst case, if all numbers in the input array are unique and we end up storing all of them in the Set. The space complexity is linear with respect to the size of the input array.
*
*
*
* Optimal Time Complexity: O(n) because we need to iterate through the array at least once to check for pairs. The use of a Set allows us to achieve this optimal time complexity by providing constant time lookups for the complement values.
*
* @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;
}
}
const seenNumbers = new Set();

for (const num of numbers) {
const complement = target - num;
if (seenNumbers.has(complement)) {
return true;
}
return false;
seenNumbers.add(num);

}

return false;
}
console.log(hasPairWithSum([4, 4], 8))
38 changes: 16 additions & 22 deletions Sprint-1/JavaScript/removeDuplicates/removeDuplicates.mjs
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
/**
* 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) - where n is the length of the input sequence, as we need to iterate through it once to create the Set.
* Space Complexity: O(n) - in the worst case, if all elements are unique, the Set will contain all elements of the input sequence. so we need memory to store the unique elements.
* Optimal Time Complexity: O(n)- using a Set to track seen values allows us to achieve linear time complexity for removing duplicates.
*
* @param {Array} inputSequence - Sequence to remove duplicates from
* @returns {Array} New sequence with duplicates removed
*/
export function removeDuplicates(inputSequence) {

return [...new Set(inputSequence)];
}


// approach 2: map and look up object
/*export function removeDuplicates(inputSequence) {
const seen = {};
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[item]) {
seen[item] = true;
uniqueItems.push(item);
}
}

return uniqueItems;
}
}*/
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@ 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(2n) = O(n) - We iterate through the list twice (once for sum, once for product)
Space Complexity: O(1) - Only using constant extra space for variables
Optimal time complexity: O(n) - We can achieve O(n) by combining both loops into one single pass
"""
# Edge case: empty list
if not input_numbers:
return {"sum": 0, "product": 1}

sum = 0
sum_value = 0
product_value = 1
for current_number in input_numbers:
sum += current_number
sum_value += current_number
product_value *= current_number

product = 1
for current_number in input_numbers:
product *= current_number

return {"sum": sum, "product": product}
return {"sum": sum_value, "product": product_value}
21 changes: 14 additions & 7 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,20 @@ def find_common_items(
"""
Find common items between two arrays.

Time Complexity:
Space Complexity:
Optimal time complexity:
Time Complexity: O(n * m) - where n is the length of the first array and m is the length of the second array.
We iterate through each element in the first array and for each element, we check if it exists
in the second array using the 'in' operator, which takes O(m) time. We also check if the item
is already in common_items using 'not in', which takes O(k) time where k is the size of common_items.
Space Complexity: O(k) - where k is the number of common items found. We store each common item in the list.
Optimal time complexity: O(n + m) - Using a hash set (dictionary/set) for the second sequence allows us to achieve
linear time by avoiding the nested loop. This reduces the lookup from O(m) to O(1).
"""
# Create a set from the second sequence for O(1) lookups
second_set = set(second_sequence)
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)

for item in first_sequence:
if item in second_set and item not in common_items:
common_items.append(item)

return common_items
22 changes: 15 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,20 @@ 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²) - where n is the length of the input array. We use two nested loops, where the outer loop
iterates through each element, and the inner loop iterates through all subsequent elements.
In the worst case, we need to check all pairs.
Space Complexity: O(1) - We only use constant extra space for loop variables.
Optimal time complexity: O(n) - Using a hash set allows us to check if the complement (target_sum - current_number)
exists in O(1) time, reducing the overall complexity from O(n²) to O(n) with one pass through the array.
"""
for i in range(len(numbers)):
for j in range(i + 1, len(numbers)):
if numbers[i] + numbers[j] == target_sum:
return True
# Optimised approach: Use a set to store seen numbers for O(1) lookups
seen_numbers = set()

for num in numbers:
complement = target_sum - num
if complement in seen_numbers:
return True
seen_numbers.add(num)

return False
19 changes: 10 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,20 @@ 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²) - where n is the length of the input sequence. For each element in the values sequence,
we iterate through all existing items in unique_items to check if it's a duplicate.
In the worst case, this requires checking all previous elements.
Space Complexity: O(k) - where k is the number of unique items. We store up to k items in the unique_items list.
Optimal time complexity: O(n) - Using a set to track seen items allows us to check for duplicates in O(1) time,
reducing the overall complexity from O(n²) to O(n).
"""
# Optimised approach: Use a set to track seen items for O(1) lookups
seen_items = 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:
if value not in seen_items:
seen_items.add(value)
unique_items.append(value)

return unique_items
Loading