Repository navigation
London | 26-SDC-July | Raihan Sharif | Sprint 1 | Analyse and Refactor Functions - #266
RaihanSharif wants to merge 13 commits into
Conversation
cjyuan
left a comment
There was a problem hiding this comment.
Both implementation and analyses are good. Well done!
| // dedupe the secondArray to reduce the number of inclues() | ||
| const secondSet = new Set(secondArray); | ||
| return [...new Set(firstArray.filter((item) => secondSet.has(item)))]; |
There was a problem hiding this comment.
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.
I see, so I guess I could something like
export const findCommonItems = (firstArray, secondArray) => {
return [...new Set(firstArray).intersection(new Set(secondArray))];
};The complexity would be the same as before.
There was a problem hiding this comment.
Yes. Same complexity. Slightly more efficient.
| 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.
How would
There was a problem hiding this comment.
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 comon_items list, which itself is O(k), and in the worst case k is min(m, n).
There was a problem hiding this comment.
Suppose the lists store integers.
Basically, where there n ^2 checks,
common_itemswill only have 1 item. So it becomes n^2 iterations * 1 check per iteration. O(n^2).
This describes the case list1 = list2 = [1, 1, 1, ..., 1]
If k is large, checking takes k time, but there are only n checks of the
common_itemslist because out n*n iterations only n of them satisfy thei == jcondition. Therefore, where k = n, the result is again n ^2.
This describes the case list1 = list2 = [1, 2, 3, 4, ..., n]
However, these two extreme but opposite cases are not the worst case scenario.
There was a problem hiding this comment.
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 [1, 2, 3, 4], then the nested loop would have to run n^2 times, and i == j would be true once per outer loop, which is n times.
The common_items list would increase by 1 at each match i == j, so the next time it’s a match and common_items is checked, the time taken would increase by 1. So the total number of checks would be (1 + 2 + 3 + … + (n-1) = n(n-1)/2 . That’s just the complexity of the common_items membership check, there’s also the complexity of the number of equality checks, so the total is n^2 + n*(n-1)/2 which is O(n^2).
The other extreme is that, the lists contain one common element, like [1, 1, 1, 1, 1] and you’d have the nested loop n^2 iterations and at each inner loop it has to check the membership ans i == j is always true. So the number of check of common_items is n^2 * 1 since the size of common items would be constant. So again, O(n^2).
These are not the worst case scenarios. The worst scenario is when you have two identical lists, but only the first half is unique: [1, 2, 3, 4, 9, 9, 9, 9] so that initially you do the checking and populating of common_items same as in the first scenario. Half way through, you now have a common_items of size n/2 . Remaining outer loops = n/2 and for each outer loop iteration there are n inner loop iterations. For half of those there’s a check of common_items and checking common_items costs n/2. So the total is outer loop (n/2) * number of common_items checks (n/2) * cost of checking common_items (n/2).
(n/2) * (n/2) * (n/2) = n^3/8 for the second half of the list. As the list grows, the O(^3) of the second half of the list dominates the O(^2) of the first half of the list, so worst case is O(n^3).
Learners, PR Template
Self checklist
Task code
CYF-1173
Changelist
Explained the original time/space complexity of each function, then refactored to the most optimal solution I could think of. Explained the complexity of the refactored version.