Repository navigation
London | 26-SDC-July | Raihan Sharif | Sprint 1 | Analyse and Refactor Functions #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
50c5a66
e91a63a
53b7a35
110abf3
806d4f1
f7057bc
d90a92f
b44aa66
30b4d9b
bf8253a
a5e2c8c
e293bc9
5e782aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,29 @@ | ||
| /** | ||
| * Finds common items between two arrays. | ||
| * | ||
| * Time Complexity: | ||
| * Space Complexity: | ||
| * Optimal Time Complexity: | ||
| * Time Complexity: O(n * m) -- where n is length of firstArray and | ||
| * m is length of secondArray. filter is O(n) and includes is o(m) for every n. | ||
| * | ||
| * Space Complexity: O(n) -- every element in firstArray could have its equivalent in secondArray. | ||
| * So in the worst case, n elements would have to be stored in the filtered array. | ||
| * Size of filtered array is k, such that k <= n. the Set (l) and the final spread array (m) are | ||
| * also smaller than n. The space used is k + l + m, so ultimately it's still O(n). | ||
| * | ||
| * Optimal Time Complexity: O(n + m) -- converting secondArray to a set gives you a O(1) lookup, | ||
| * with secondSet.has(item). So filter becomes O(n * 1) rather than O(n * m). | ||
| * | ||
| * Converting an array to a Set is a O(m) operation, since every element in secondArray (size of m), | ||
| * must be checked. As this only done once at the start, rather than for every element in firstArray. | ||
| * The final time complexity is O(n + m). | ||
| * | ||
| * However, there is increased space complexity of O(n + m) as a set of size m now needs to be stored. | ||
| * | ||
| * @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) => { | ||
| // dedupe the secondArray to reduce the number of inclues() | ||
| const secondSet = new Set(secondArray); | ||
| return [...new Set(firstArray.filter((item) => secondSet.has(item)))]; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,28 @@ | ||
| /** | ||
| * 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^2) -- if there is no pair that their sum = target, | ||
| * or its is the last two items then the function has to loop over every element, | ||
| * and for each element loop n-1, n-2, n-3, ..., 0 times. | ||
| * Total comparisons is n(n-1)/2 = (n^2 - n)/2. In big O terms that's just O(n^2). | ||
| * | ||
| * Space Complexity: O(1) -- space used does not grow with input size. | ||
| * | ||
| * Optimal Time Complexity: O(n) -- At worst, makes one pass through the array. | ||
| * All operations inside of the loop are O(1). | ||
| * | ||
| * @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 seen = new Set(); | ||
|
|
||
| for (const num of numbers) { | ||
| if (seen.has(target - num)) { | ||
| return true; | ||
| } | ||
| seen.add(num); | ||
| } | ||
| return false; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,20 @@ | ||
| /** | ||
| * 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^2) -- In the worst case, the number of comparisons in each step of the iteration | ||
| * increases by 1 because uniqueItems grows by 1. It goes 0 + 1 + 2 + ... + (n-1), so total number of | ||
| * comparisons is n(n - 1)/2 = (n^2 - n)/2. Big O discards the constant factor (1/2) and the lower-order term (n), leaving n^2. | ||
| * | ||
| * There aren't exactly n^2 comparisons, but big O doesn't care about that. | ||
| * | ||
| * Space Complexity: O(n) -- uniqueItems can hold up to n items when all items are unique. | ||
| * | ||
| * Optimal Time Complexity: O(n) -- Adding each element of the input sequence to the set is a O(1) (on average) operation, | ||
| * and then another O(n) operation to convert to an array with the spread operation. | ||
| * | ||
| * @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; | ||
| return [...new Set(inputSequence)]; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,13 +9,25 @@ def find_common_items( | |
| """ | ||
| Find common items between two arrays. | ||
|
|
||
| Time Complexity: | ||
| Space Complexity: | ||
| Optimal time complexity: | ||
| Time Complexity: O(n * m * k) -- where n = length of first_sequence, m = length of second_sequence, | ||
| k = length of common_items. k <= min(n, m) because common_items can never be bigger than the smaller | ||
| of the two sequences. As common_items is a list, checking membership is a linear time operation. | ||
|
|
||
| Complexity class is O(n^2) if two are sequences are same size. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think k is what makes it a cubic complexity rather than quadratic complexity. Because the looping by itself is quadratic, but in the worst case there are n checks of the membership of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suppose the lists store integers.
This describes the case
This describes the case However, these two extreme but opposite cases are not the worst case scenario.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I've finally figured it out. If we take a pair of identical lists which have all unique values, and all values are in common, such as The The other extreme is that, the lists contain one common element, like These are not the worst case scenarios. The worst scenario is when you have two identical lists, but only the first half is unique:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spot on! Excellent work. |
||
|
|
||
| Space Complexity: O(n) -- If every item in first_sequence is also in second_sequence, then the entirety of n | ||
| has to be stored in common_items. Techincally it's O(min(n, m)). | ||
|
|
||
| Optimal time complexity: O(m + n) -- O(m) to convert second_sequence to a set, then. O(n) to iterate through | ||
| the first_sequence. All operations inside the loop are O(1) (more or less), so additional complexity. | ||
| """ | ||
| second_set = set(second_sequence) # O(m) | ||
| seen = set() | ||
| 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: # n iterations | ||
| if item in second_set and item not in seen: # O(1) average lookups, times 2 | ||
| seen.add(item) # O(1) average insertion | ||
| common_items.append(item) # O(1) | ||
|
|
||
| return common_items | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note:
Most Set implementations support the common set operations such as union, intersection, difference, subset, superset, equality, add, remove, contains, size, clear, and is empty.
You could also take advantage of these built-in methods for better performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, so I guess I could something like
The complexity would be the same as before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Same complexity. Slightly more efficient.