https://github.com/dimitrisjim/leetcode_solutions
Solutions to leetcode problems in Python, Rust, C and JavaScript.
https://github.com/dimitrisjim/leetcode_solutions
c javascript leetcode python rust
Last synced: 2 months ago
JSON representation
Solutions to leetcode problems in Python, Rust, C and JavaScript.
- Host: GitHub
- URL: https://github.com/dimitrisjim/leetcode_solutions
- Owner: DimitrisJim
- License: unlicense
- Created: 2020-10-06T23:27:22.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2022-11-02T11:55:26.000Z (over 3 years ago)
- Last Synced: 2025-06-22T17:08:22.644Z (12 months ago)
- Topics: c, javascript, leetcode, python, rust
- Language: C
- Homepage:
- Size: 1.62 MB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# LeetCode problems.
Some small notes:
- I usually use the best execution/memory numbers I can achieve.
Sometimes this makes me write code which is what you would call
premature optimization (especially in Python.)
- Rust seems to optimize very well and uniformly, leading
to `100%` execution/memory consistently. (Update: Low number of submissions
also has an effect.
- Search for `TODO: Improve` for places where I think I've messed up slightly
(also see Revisit.md).
- Problems that are new have skewed timings because of the initial low
number of submissions.
- I might skip some `C` problems when the time needed to create the structures far outweights the benefit.
Most times it is relatively straight-forward after a solution has been found.
Additionally:
- Python and C also have a Concurrency folder where attempts at the concurrency problems are
added. I will not offer any sort of guarantees on those.
## [1. Two Sum.][1]
Similar to other Two Sum problems. We again use a cache in the form of a mapping
that keeps track of the appropriate index to use when we finally find the match.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 96.96 | 0 - 100.00 | 72 - 94.33 | 28 - 99.99 |
| Mem Usage (MB-%)| 6 - 68.00 | 2.3 - 68.01 | 38.4 - 91.28 | 14.4 - 47.87 |
## [2. Add Two Numbers.][2]
Traverse each list and build the counts as we go. Reuse one of the lists instead of
allocating new nodes all the time. All in all, this has `O(N)` worse case runtime complexity
where `N` is the size of the largest linked list.
Rust: Not sure how exactly I should do this :(.
TODO: Revisit.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 95.93 | - | 120 - 97.43 | 56 - 98.88 |
| Mem Usage (MB-%)| 7.2 - 96.67 | - | 44 - 72.19 | 14.2 - 90.81 |
## [7. Reverse Integer.][7]
We can work with arrays of the digits in order to reverse the numbers. Care needs to be
taken specifically for largest negative `i32 (0x80000000)` and for inputs that contain
`10` digits in total (which, when reversed, might not fit in 32 bits).
To combat first case, we can just bail early if `x == 0x80000000`. To combat the second case,
we check the digits of the result against the maximum value allowed. If, at any point, we discover
input the would result in a number too large to represent, we bail.
Overall, this is `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 88 - 94.61 | 20 - 99.44 |
| Mem Usage (MB-%)| 6 - 14.40 | 1.9 - 85.78 | 40.8 - 14.78 | 14.4 - 11.58 |
## [9. Palindrome Number.][9]
Common string version, transform to string and then go through from both ends
trying to find a mismatch. `O(num_of_digits)` basically.
Without transforming to string: You could do something similar by divmoding to
find the first digits and divmoding again to find last. At least, that's what
I'm thinking now. TODO: look this up.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 92.79 | 0 - 100.00 | 196 - 96.90 | 48 - 94.22 |
| Mem Usage (MB-%)| 6.2 - 10.13 | 2.2 - 31.71 | 49.1 - 36.11 | 14.2 - 49.05 |
## [13. Roman to Integer.][13]
Keep a set of the special cases and go through each character in `s`. If the character
we've currently looking at and its next one are in the special cases, handle the case
and increase our counter to then look at the next character two positions over. Else,
just add the character seen.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 89.64 | 0 - 100.00 | 152 - 95.49 | 36 - 97.76 |
| Mem Usage (MB-%)| 5.7 - 98.67 | 2 - 92.20 | 44.4 - 92.17 | 14 - 94.68 |
## [14. Longest common prefix.][14]
First string is initialized as the prefix. We iterate through the rest of the strings
and continuously reduce this prefix. Process stops when all strings have been seen or
if the prefix becomes empty at some point during the iteration.
Space complexity it `O(1)`, time complexity is `O(NM)` where `N` is the number of
strings and `M` the length of the strings.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 97.82 | 28 - 94.45 |
| Mem Usage (MB-%)| 5.8 - 96.22 | 2.1 - 75.69 | 39.7 - 62.36 | 14 - 99.12 |
## [21. Merge two sorted lists.][21]
For `Rust`, go through both linked lists and build vector of values, then, build
resulting vector.
For others, go through nodes of linked list and incrementally build resulting linked
list.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 4 - 100.00 | 84 - 92.62 | 32 - 91.62 |
| Mem Usage (MB-%)| 6.3 - 47.94 | 2 - 83.19 | 40.1 - 91.86 | 14.1 - 83.79 |
## [24. Swap nodes in pairs.][24]
Relatively straight-forward though the swapping is easy to get wrong. Keep track
of previous in line (to point to new next), the current pairs (cur, next) we are
swapping and perform the swap.
This touches each node once so `O(N)` time with `O(1)` space.
Rust: I probably need to read Too Many Linked Lists, again.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | - | 72 - 92.46 | 20 - 99.11 |
| Mem Usage (MB-%)| 5.8 - 60.54 | - | 38.7 - 71.53 | 14.3 - 48.70 |
## [27. Remove Element.][27]
Use a swap-remove. As found in Rusts `Vec.swap_remove`. Basically, replace the
value you want to remove with the value at the end of the list/array. This way,
`O(1)` removes can be achieved. Overall complexity is `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 98.77 | 28 - 90.92 |
| Mem Usage (MB-%)| 6.1 - 39.77 | 2.1 - 67.18 | 38.6 - 60.38 | 14.3 - 46.75 |
## [28. Implement Strstr.][28]
After handling special edge cases (`needle == ""` and `len(needle) > len(haystack)`) we
go through the haystack and compare sub-slices. Need to break out early if a subslice doesn't
match. Worse case is still `O(nm)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 99.08 | 24 - 95.52 |
| Mem Usage (MB-%)| 5.8 - 95.27 | 2.2 - 58.11 | 39.4 - 41.95 | 14.5 - 24.15 |
## [31. Next Permutation.][31]
This basically uses the algorithm described [here](https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order).
In short, find index `i` such that for all `j` > `i` `nums[j] > nums[j+1]`. Swap the value with the smallest value that's larger
than the value at index `i`. Reverse the contents of the array for `j > i`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 98.86 | 0 - 100.00 | 76 - 94.00 | 28 - 99.78 |
| Mem Usage (MB-%)| 6.1 - 78.86 | 2 - 56.25 | 40.5 - 28.99 | 14.3 - 52.14 |
## [34. Find first and last position of element in sorted array.][34]
Use binary searches to find start/end.
C: todo, too bored to implement binary search (again!)
| Stats/Lang | C | Rust | Go | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 0 - 100.00 | 6 - 91.00 | 75 - 99.81 |
| Mem Usage (MB-%)| - | 2.3 - 78.42 | 3.9 - 99.90 | 15.4 - 49.40 |
## [35. Search insert position.][35]
Again, binary searching for the right spot, i.e `O(logN)`.
Start points to position in list for which all elements with index smaller than start have a value
than target and all elements with index larger than it have a `value >= target`.
When finished, start will either point to target or the leftmost position in which to insert it.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 98.11 | 40 - 97.25 |
| Mem Usage (MB-%)| 6 - 85.77 | 2 - 100.00| 38.7 - 72.22| 15.1 - 52.12 |
## [46. Permutations.][46]
This basically uses the algorithm described [here](https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order).
In short, find index `i` such that for all `j` > `i` `nums[j] > nums[j+1]`. Swap the value with the smallest value that's larger
than the value at index `i`. Reverse the contents of the array for `j > i`.
The only difference between this problem and `31.` is that here we stick it all in a loop and we sort the sequence before
we enter the loop (in order to start from 'smallest' permutation).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 95.45 | 0 - 100.00 | 80 - 96.09 | 32 - 97.03 |
| Mem Usage (MB-%)| 7.1 - 85.61 | 2.1 - 86.49 | 41.8 - 49.81 | 14.3 - 70.48 |
## [50. Pow(x, n).][50]
Uses binary exponentiation (exponentiation by squaring) to cut down on the number
of multiplications performed to `O(logn)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 95.48 | 24 - 96.07 |
| Mem Usage (MB-%)| 5.5 - 61.56 | 2 - 88.89 | 40.5 - 8.33 | 14 - 92.69 |
## [53. Maximum Subarray.][53]
Can keep track of largest running sum while going through the array. Initially, I used a table to keep track
of the values seen as the following code illustrates:
```python
def maxSubArray(self, nums: List[int]) -> int:
length, maximum = len(nums), nums[0]
table = [0] * len(nums)
table[0] = nums[0]
for i in range(1, length):
cur, prev = nums[i], table[i-1]
if (s := cur + prev) > cur:
table[i] = s
else:
table[i] = cur
if table[i] > maximum:
maximum = table[i]
return maximum
```
Of course, after closer examination, we can see we only need to know the previous value in order to keep track of the
running sum (we always access `table[i-1]` and `table[i]`, hinting that one variable whose value we update could do the
trick.)
Uses `O(N)` time and `O(1)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 97.38 | 0 - 100.00 | 68 - 99.79 | 60 - 89.66 |
| Mem Usage (MB-%)| 6.2 - 97.47 | 2.1 - 97.32 | 38.9 - 87.32 | 14.9 - 78.41 |
## [58. Length of last word.][58]
If the length is easily (`O(1)`) available, walk the string backwards and return the second time we reach
a space. If length isn't available, traverse until the end continuously updating the count per word and return
the final value of count stored. All in all, `O(N)` runtime with `O(1)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 99.72 | 20 - 98.80 |
| Mem Usage (MB-%)| 5.8 - 55.26 | 2.1 - 78.18 | 38.5 - 58.54 | 14.4 - 6.90 |
## [61. Unique paths.][61]
DP with tabulation. Start with an initial value of `1` in 2d table position `[0][0]` (start) and then add
values from the left and top as the table is traversed (signifying moves made right and down).
Final answer is at last position (end.)
Space and time complexity is `O(mn)`.
Note: there's definitely a space optimization here. Only work with 2 rows at a time.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 98.41 | 20 - 99.30 |
| Mem Usage (MB-%)| 5.8 - 24.15 | 2 - 94.44 | 39.6 - 23.46 | 14.2 - 65.47 |
## [63. Unique paths II.][63]
DP with tabulation. Start with an initial value of `1` in 2d table position `[0][0]` (start) and then add
values from the left and top as the table is traversed (signifying moves made right and down). Make sure
to ignore positions with obstacles and to only add if we came from free positions.
Final answer is at last position (end.)
Space and time complexity is `O(mn)`.
Note: there's definitely a space optimization here. Only work with 2 rows at a time.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 98.42 | 36 - 94.99 |
| Mem Usage (MB-%)| 6 - 71.08 | 2.1 - 60.00 | 39.5 - 45.34 | 14.1 - 94.87 |
## [64. Summary Ranges.][64]
Keep a tracker around to track the sequence as it increases. If at any point, the number in
the array doesn't match the tracker, a new sequence should be added. Care is needed when
ending the loop to accound for two cases (ended on a single number or while going through a
range). Overall, `O(N)` time and space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 97.06 | 24 - 93.79 |
| Mem Usage (MB-%)| 5.7 - 73.33 | 2.1 - 54.55 | 38.2 - 92.51 | 14.4 - 16.10 |
## [66. Plus One][66]
Relatively straight-forward, if we encounter a `9`, we need to zero it and move
left to the next item in the array. If it isn't a nine, we increment and return.
Care is needed to detect when the array is basically full of `9`s in which case we
need to prepend a `1` before we return.
Runtime complexity is `O(N)`, we perform constant operations for each item in the
array. Space complexity is `O(1)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 99.75 | 24 - 97.53 |
| Mem Usage (MB-%)| 5.8 - 99.54| 2 - 93.75 | 38.6 - 69.35 | 14.3 - 48.72 |
## [69. Sqrt(x).][69]
Use [babylonian method](https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
for finding square roots. Initial guess is `x / 2` and we converge by taking the arithmetic mean of
`guess, x / guess` until `guess * guess` is `<= x`.
I am not sure about the complexity, a quick search yields `O(log(log(n/m)))` where `n` is our input
and `m` is the error during the approximation. Since we don't mind large errors (require integer result)
`n/m` small (i.e nearing `n`).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 99.77 | 28 - 94.96 |
| Mem Usage (MB-%)| 5.5 - 90.98 | 2 - 91.18 | 40.2 - 21.04 | 14.3 - 6.07 |
## [70. Climbing stairs.][70]
Pretty much similar to finding the `n`th fibonacci number. `O(N)` time with `O(1)` space (we only need
to keep track of previous two values.)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 96.42 | 24 - 92.99 |
| Mem Usage (MB-%)| 5.4 - 99.04 | 2 - 87.23 | 38.3 - 74.43 | 13.8 - 99.83 |
## [74. Search a 2d matrix.][74]
Perform a binary search on each of the rows. `O(nlogn)` runtime and `O(1)` space. Also solves
problem `240` but not so efficiently.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 95.05 | 32 - 98.77 |
| Mem Usage (MB-%)| 6.1 - 84.76 | 2.1 - 78.57 | 38.5 - 87.74 | 14.8 - 62.06 |
## [78. Subsets.][78]
Trick also utilized in Knuth 4A, view subsets as bitstrings of length `size(input)` with members
being denoted by a set bit for the appropriate position. That is, for input of the form `[1, 2, 3, 4]`
we'd have:
```
0000 0001 0010 0100 1000 0011 0101 1001 0110 1010 1100 0111 ...
```
where these denote the subsets:
```
{0}, {1}, {2}, {3}, {4}, {1, 2}, {1, 3}, {1, 4}, {2, 3}, {3, 4}, {1, 2, 3} ...
```
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 99.13 | 0 - 100.00 | 72 - 98.13 | 28 - 92.84 |
| Mem Usage (MB-%)| 6.5 - 65.22 | 2 - 90.00 | 39.6 - 73.46 | 14.4 - 51.70 |
## [83. Remove duplicates from sorted list.][83]
Traverse and update the next pointers/references. `O(N)` time.
Rust: LinkedList chaos.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | - | 72 - 99.25 | 36 - 94.09 |
| Mem Usage (MB-%)| 6.4 - 93.20 | - | 40.6 - 44.91 | 14 - 94.35 |
## [88. Merge sorted array.][88]
Place elements from `nums2` at the end of `nums1` (replacing zero elements) and sort it.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 98.93 | 28 - 96.98 |
| Mem Usage (MB-%)| 6.2 - 39.46 | 2 - 66.67 | 38.5 - 92.89 | 14.2 - 85.77 |
## [94. Binary Tree Inorder Traversal.][94]
Python + JS use iterative approach. C + Rust use recursive. With C, going iterative is
relatively trivial, for Rust, not so much (and I'm really not sure how you'd do it without
having TreeNode be clone'able [and even that sounds like a nasty approach]).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 93.61 | 12 - 95.37 |
| Mem Usage (MB-%)| 5.7 - 95.00 | 1.9 - 94.29 | 38.5 - 79.11 | 13.3 - 75.85 |
## [100. Same Tree][100]
C recursively solves it while the others use the iterative approach. In all cases
this really just involves traversing the same nodes and checking that their values
are the same and they both have the same numbers of children.
Care is needed to handle case where one tree has been exhausted while the other tree
still has nodes we haven't seen.
Complexity is `O(N)` where N is the number of nodes since we perform constant
operations for each node. Not sure about space complexity of the top of my head.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 92.99 | 24 - 95.46 |
| Mem Usage (MB-%)| 6 - 34.24 | 2 - 52.17 | 38.8 - 77.73 | 14.2 - 65.65 |
## [101. Symmetric Tree.][101]
Walk both subtrees in a symmetric way (when we walk left on one, we walk right on
the other and vise versa). This relationship can be captured either via a normal
stack or the call stack of a function.
Python, Rust, Javascript use a list/vector to order the traversal down both branches while
C is recursive. `O(N)` for either case (memory and runtime)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 84 - 90.33 | 28 - 92.94 |
| Mem Usage (MB-%)| 6.7 - 98.62 | 2 - 73.53 | 40.6 - 35.90 | 14.6 - 10.69 |
## [102. Binary Tree level order traversal.][102]
There's a similar problem to this one, I remember it. All in all, use a stack where we
keep nodes/level tuples. DFS traversal and use the level saved for each node as index in
the results vec/list that holds the result values. `O(N)` space/memory.
C: Too much hassle with 2D arrays but I hope I'll get back to it.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | 0 - 100.00 | 80 - 85.22 | 24 - 98.58 |
| Mem Usage (MB-%)| | 2 - 97.96 | 40.3 - 44.58 | 14.5 - 88.37 |
## [104. Maximum depth of Binary Tree][104]
Rust contains both iterative and recursive approaches. C/Javascript use
recursive, Python uses iterative.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 92.16 | 0 -100.00 | 80 - 94.64 | 36 - 89.43 |
| Mem Usage (MB-%)| 8.1 - 50.63 | 2.5 - 94.87 | 41 - 96.55 | 15.2 - 91.21 |
## [107. Binary Tree Level Order Traversal II,][107]
Breadth first traversal, use an additional value to mark the level which we use to
correctly place into subarrays. Return result reversed.
C Version: Not mentally ready to go through the allocation hell, yet.
Complexity: Time should be `O(N)`, not sure about space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| Nope. | 0 - 100.00 | 76 - 95.89 | 24 - 98.69 |
| Mem Usage (MB-%)| NOPE. | 2.1 - 88.89 | 40.3 - 25.94 | 14.7 - 49.77 |
## [108. Convert Sorted Array to BST.][108]
Need to balance resulting tree (i.e max difference of height between two children of
a given node to equal 1).
Since we have a sorted array, we know we can separate the array in a triplet consisting
of `(lower_than_mid, mid, higher_than_mid)`. Using this we can then use:
- `mid`: as our new node.
- `lower_than_mid`: as our left branch.
- `higher_than_mid`: as our right branch.
Recursively solving this is straight-forward.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 94.69 | 0 - 100.00 | 84 - 95.62 | 56 - 99.93 |
| Mem Usage (MB-%)| 18 - 59.59 | 2.9 - 71.43 | 41.7 - 93.78 | 16.6 - 22.27 |
## [110. Balanced Binary Tree.][110]
Need to go through tree and calculate differences between subtrees for every given node.
Doing this naively results in a lot of repetition of work (think fibonacci). So, a cache
can be utilized that holds the height for a given node.
Approaches here use recursion, C version is TODO for when I'm up for using uthash again. Got
Rust version to work but cache requires raw pointers as keys, I feel a better approach should
exists and I'm under the impression an iterative solution would be better. As such, that is
another TODO.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 4 - 100.00 | 92 - 77.70 | 40 - 97.82 |
| Mem Usage (MB-%)| - | 2.9 - 12.50 | 43 - 62.04 | 18.9 - 48.15 |
## [111. Minimum depth of binary tree.][111]
Typical depth first recursion. We can stop recursing when we reach a depth which is bigger
than a minimum we've already found, though. Worse case complexity is still `O(N)` as is the
memory complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 132 - 99.58 | 32 - 97.73 | 232 - 99.61 | 468 - 93.47 |
| Mem Usage (MB-%)| 75.4 - 99.16 | 11.4 - 100.00 | 75.4 - 17.90 | 49.3 - 72.86 |
## [112. Path Sum.][112]
Rust and Python have iterative solutions while C/Javascript have recursive. The idea
in both cases is the same, recurse while holding on to the current sum and, when we
reach a leaf, check if sums match.
`O(N)` both space and runtime complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 96.72 | 0 - 100.00 | 80 - 97.72 | 36 - 93.49 |
| Mem Usage (MB-%)| 8.4 - 15.54 | 2.5 - 92.31 | 42.2 - 31.94 | 16 - 24.23 |
## [113. Path Sum II.][113]
Rust and Python have iterative solutions while Javascript have recursive. The idea
in both cases is the same, recurse while holding on to the current sum, the level (depth) and
the path of nodes encountered. When we encounter a level with value `<=` then the length of the
list of nodes (path), we trim the path to bring the path to the correct position.
When we reach a leaf, check if sums match and, if they do, yield/store the path.
`O(N)` both space and runtime complexity.
TODO: `C` version isn't hard just requires manual management for the arrays holding paths, list
of paths which I've burned out doing over and over.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 0 - 100.00 | 88 - 95.02 | 36 - 97.12 |
| Mem Usage (MB-%)| - | 2.5 - 100.00 | 49.6 - 25.25 | 14.9 - 99.21 |
## [118. Pascal's triangle.][118]
Becomes easy once you look up on Pascal's Triangle and find the [formula for
finding a row](https://en.wikipedia.org/wiki/Pascal%27s_triangle#Calculating_a_row_or_diagonal_by_itself).
Not sure about complexity here. Since for each `n` we perform `1 + 2 + 3 + .... + n`
iterations, though, I believe it must be around `O(n^2)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 99.32 | 24 - 95.43 |
| Mem Usage (MB-%)| 5.9 - 95.86 | 2.3 - 6.67 | 38.6 - 21.82 | 14.3 - 59.05 |
## [116. Populating next right pointers in each node.][116]
The only issue is when you need to link two "cousins" (children of uncle nodes) together.
In order to do that, we just use `node->next` that has been filled in previous recursion/iteration
to go to the uncle and access his children. Care needs to be taken on what we link right has priority
on the left side while left has priority on the right side, i.e:
```
# link 3 to 4 but if 3 doesn't exist, link 9 to 4 and
# if 4 doesn't exist, link 3 or 9 to 5.
root
/ \
4 7
/ \ / \
9 3 4 5
```
Complexity is `O(N)` both runtime and space (counting implicit call stack).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 83.52 | N/A | 92 - 95.75 | 52 - 97.91 |
| Mem Usage (MB-%)| 8.8 - 97.80 | N/A | 45.2 - 72.90 | 15.5 - 99.07 |
## [119. Pascal's triangle II.][119]
Becomes easy once you look up on Pascal's Triangle and find the [formula for
finding a row](https://en.wikipedia.org/wiki/Pascal%27s_triangle#Calculating_a_row_or_diagonal_by_itself).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 99.83 | 24 - 96.72 |
| Mem Usage (MB-%)| 5.9 - 65.63 | 2.4 - 5.00 | 38.3 - 82.37 | 14.3 - 54.93 |
## [121. Best time to buy and sell stock.][121]
Continuously holds the minimum encountered thus far. When a
value is not smaller, we see if it exceeds the max_price as
has been set thus far. For example:
[1, 2, 3, 0, 20, 0, 30, 5, 6]
min_price is initialized to `prices[0]` first (by default, the minimum
encountered thus far). Our max_price during the iteration tracks the
following subtractions:
price == 1: => min_price = 1, max_price = 0 (dummy iteration, really)
price == 2: => min_price = 1, max_price = 1 (2 - 1)
price == 3: => min_price = 1, max_price = 2 (3 - 1)
....
price == 30 => min_price = 0, max_price = 30 (30 - 0). (Final answer)
Runs in O(N) with O(1) space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 96 - 100.00 | 8 - 97.35 | 92 - 93.75 | 952 - 83.52 |
| Mem Usage (MB-%)| 13 - 43.30 | 3.1 - 23.18 | 48.5 - 90.30 | 25 - 95.24 |
## [122. Best time to buy and sell stock II.][122]
Buy on local minimums and sell on local maximums. This can be done by going through
the prices in pairs and buying only if the price of the previous day was smaller
than that of the next day and only selling if the price of the previous day is larger
than that for the next.
A toggle for the action is used to differentiate the cases (buying/selling).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 97.15 | 0 - 100.00 | 76 - 92.04 | 52 - 96.93 |
| Mem Usage (MB-%)| 6.9 - 46.64 | 2.1 - 76.47 | 39.2 - 72.89 | 15.1 - 54.54 |
## [125. Valid Palindrome.][125]
Strip unwanted characters, transform to uppercase and check if the remaining characters form a palindrome.
| Stats/Lang | C | Rust | Go | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 3 - 82.32 | 37 - 99.32 |
| Mem Usage (MB-%)| 6.3 - 73.04 | 2.2 - 91.42 | 3.3 - 45.58 | 15.3 - 24.50 |
## [133. Clone graph.][133]
Recurse on neighbors and gradually build the graph, need to keep track of what we've visited
in order to not recurse like crazy. Both time and space complexity should be `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 87.32 | N/A | 72 - 98.91 | 32 - 92.73 |
| Mem Usage (MB-%)| 6.9 - 76.06 | N/A | 39.7 - 98.91 | 14.7 - 26.45 |
## [136. Single Number][136]
Pretty well known xor trick. Based on the property that xor of two equal
numbers is zero.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 99.30 | 0 - 100.00 | 80 - 92.47 | 112 - 99.63 |
| Mem Usage (MB-%)| 7.1 - 99.80 | 2.1 - 81.55 | 39.9 - 98.51 | 16.7 - 29.16 |
## [141. Linked list cycle.][141]
You could use two pointers, one ahead of the other and keep iterating until they
meet (or a `None/NULL/null` is encountered). If doing destructive mutations on the
linked list was allowed, you could alter the next pointer of all nodes to a dummy
node and iterate until you meet that or a `None/NULL/null` (but I doubt that
would be a good idea in general).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 99.80 | N/A | 80 - 94.82 | 44 - 97.97 |
| Mem Usage (MB-%)| 7.7 - 95.40 | N/A | 41 - 72.35 | 17.5 - 91.05 |
## [144. Binary Tree Preorder Traversal.][144]
Iterative approach for Python/Rust/Javascript. C uses recursive in order to avoid
managing memory for stack needed in that case (which is implicitly provided in recursive
case).
All display `O(N)` runtime/memory complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 94.45 | 24 - 94.50 |
| Mem Usage (MB-%)| 6 - 52.38 | 2 - 55.56 | 38.7 - 62.16 | 14 - 91.16 |
## [145. Binary Tree Postorder Traversal.][145]
Iterative approach for Python/Javascript. C and Rust use recursive solutions. For C, the
changes in order to make it iterative are relatively trivial, for Rust, not sure how easily you could
make it work iteratively.
All display `O(N)` runtime/memory complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 98.51 | 24 - 94.52 |
| Mem Usage (MB-%)| 5.9 - 61.46 | 2 - 94.12 | 38.6 - 59.70 | 14.1 - 74.99 |
## [155. Min Stack.][155]
See each file for detailed comments. Basically, hold min around and update it if we
pop it off at any point.
All operations other than pop (which is `O(N)`) are done in `O(1)` or amortized `O(1)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 24 - 97.52 | 0 - 100.00 | 112 - 96.23 | 48 - 99.24 |
| Mem Usage (MB-%)| 12.6 - 93.39 | 5.5 - 96.15 | 45.4 - 71.54 | 17.9 - 66.92 |
## [167. Two sum II input array is sorted.][167]
Array is sorted, use two counters (start, end) and increase, reduce respectively
until we reach our target sum.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 99.02 | 0 - 100.00 | 72 - 97.24 | 56 - 95.51 |
| Mem Usage (MB-%)| 6.6 - 99.02 | 2.1 - 60.71 | 38.8 - 71.96 | 14.5 - 91.92 |
## [171. Excel Sheet column number][171]
To find the column number we can follow the following formula where `s` is the input
string and `n` is its length:
```
col = sum((charCodePoint - 64) * (pow(26, i)) for i in [0..n])
```
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 88 - 95.33 | 24 - 96.97 |
| Mem Usage (MB-%)| 5.6 - 69.08 | 2 - 100.00 | 39.8 - 84.74 | 14.2 - 66.98 |
## [190. Reverse Bits.][190]
Count how many leading zeros exist in a 32bit padded (with zeros from MSB) version of the input number. Then just
add the bits from the input number to the result. This is done by shifting the result left by one and adding `n & 1` to
it and then shifting `n` to the right. Finally, we shift right as many times as we counted for the leading zeroes.
Javascript: couldn't adapt same solution. TODO.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | - | 28 - 87.17 |
| Mem Usage (MB-%)| 5.3 - 75.25 | 2 - 71.43 | - | 14.3 - 8.01 |
## [191. Number of 1 bits.][191]
Not much point in adding things here. The most efficient implementation is discussed in the [wiki page](https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation) which also discusses a good strategy to optimize by using a cache of the result for all 16
bit sequences (which we can use for 32bit numbers by viewing them as two 16bit sequences).
For all intents and purposes, the algorithm I would run (if the language doesn't offer an implementation (rust, python do)) would be the
common iterative `O(N)`:
int count = 0;
while (n) {
n &= n - 1;
count += 1;
}
return count;
## [199. Binary Tree Right Side View.][199]
Traverse tree rightwards assigning levels to each node encountered. By using a stack
we can always push the rightmost values first and register them as we encounter them.
For each new level, we always register the rightmost node present in that level.
Overall needs `O(N)` execution time (since we traverse the full tree) and `O(N)` worse
case memory.
C: Could easily do this if I didn't despise having to manually track dynamic memory.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 0 - 100.00 | 72 - 99.10 | 20 - 99.43 |
| Mem Usage (MB-%)| - | 2.1 - 66.67 | 40.3 - 63.83 | 14.4 - 19.91 |
## [201. Bitwise and of numbers range.][201]
First interesting property, took me some time to notice.
If there's a difference in 1 bit it means, in the range
`[left, right]` there exists a number with the binary repr
`100....000` (`right.bit_length() - 1` zeroes) that completely
zeroes out all numbers smaller than it. The result, regardless
the range, will be 0. As a consequence, numbers that don't have a bit
representation of equal length automatically result to zero.
Second interesting property, way more time to notice.
The result, when the number of bits in the numbers is equal, is
equal to the binary number who's prefix is equal to the equal
prefixes of left and right. The rest of the bits are zero.
An example might better illustrate this:
```
left = 2146738493, right = 2147483647
```
And, in binary:
```
left = '1111111111101001010000100111101'
right = '1111111111111111111111111111111'
```
The result will be:
```
'1111111111100000000000000000000' == 2146435072
```
I.e the common prefix of left and right, `'11111111111'` followed by zeroes `'00000000000000000000'`.
This makes sense in the same way the first observation does. In the range between `left` and `right`,
the different combinations of `0` and `1` completely cancel each other out (and, by definition, all
combinations will exist between `'11110..'` and `'11111..'`).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 95.59 | 0 - 100.00 | 160 - 100.00 | 36 - 99.83 |
| Mem Usage (MB-%)| 5.7 - 97.79 | 2 - 72.73 | 47 - 24.00 | 14.2 - 83.45 |
## [206. Reverse Linked List][206]
`C` contains both iterative and recursive. The rest use iterative.
Note: Needless to say, Rust timings seem a bit off! Check again if you see
this in the future, future me.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 81.03 | 280 - 100.00 | 80 - 84.82 | 32 - 85.73 |
| Mem Usage (MB-%)| 6.2 - 98.35 | 2.5 - 51.56 | 40 - 94.38 | 15.4 - 69.73 |
## [217. Contains Duplicate.][217]
Can use a set and check if we've seen an element before (or, build a full set and
compare its size against that of the size of the original array.)
(`C` and `uthash` again seem slow)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 24 - 41.52 | 0 - 100.00 | 76 - 98.14 | 108 - 96.99 |
| Mem Usage (MB-%)| 17 - 10.73 | 2.7 - 84.62 | 45 - 54.84 | 20.1 - 81.21 |
## [219. Contains Duplicates II.][219]
Keep track of the most recent index seen in a map. When we encounter a value already contained
in the map, check if the diff of the indices is smaller than `k`. If so, return `true`, else, update
the `index` to hold the newly seen index. `O(N)` both space and runtime complexity.
For C: uthash can easily be used. A list-as-a-map cannot, as far as I can see, values contained exceed
list size.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 0 - 100.00 | 76 - 99.60 | 88 - 91.05 |
| Mem Usage (MB-%)| - | 4.2 - 28.57 | 44.5 - 58.12 | 21.8 - 54.83 |
## [220. Contains Duplicate III.][220]
Sort the numbers array after transforming it into a list holding [index, value] pairs
(enumerate its values). After doing that, we can start from the beginning and check
pairs for which the difference in value is `<= t`, larger values aren't considered.
For each pair for which `v2 - v1 <= t`, we check if the diff of their indices is
` <= k`.
Worse case is `O(N ** 2)` but that manifests only for extremely large values of `t`.
Note: I'm under the impression that another way might exist. My lackluster memory timings
and not being able to crack 90% with Python hints at this.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 16 - 100.00 | 0 - 100.00 | 108 - 92.61 | 104 - 82.89 |
| Mem Usage (MB-%)| 8 - 7.69 | 2.4 - 33.33 | 45.6 - 6.82 | 18.1 - 11.80 |
## [225. Implement Stack Using Queues.][225]
Don't particularly like these problems (also see Queue using Stacks). I'll just
add the Python solution, not really planning on adding others.
Uses a single queue actually since I really couldn't see the point of using a
second queue instead of rotating, adjusting to use second queue is straight-forward.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| N/A | N/A | N/A | 24 - 94.57 |
| Mem Usage (MB-%)| N/A | N/A | N/A | 14.4 - 46.41 |
## [226. Invert Binary Tree][226]
Most (`C`, `Javascript` and `Rust` (because I hate myself, apparently))
use recursion to swap the nodes. Python uses an iterative approach by
utilizing a stack.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 95.23 | 20 - 99.04 |
| Mem Usage (MB-%)| 5.8 - 99.02 | 2 - 88.89 | 38.9 - 55.11 | 14.2 - 39.78 |
## [231. Power of two.][231]
`x = 2 ** n <=> n = log2(x)`. For non-powers of two `log2(x)` is not an integer. This boils down
to checking if `log2(x)` is an integer which can be done with `ceil(log2(x)) == log2(x)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 80 - 98.66 | 24 - 95.94 |
| Mem Usage (MB-%)| 5.5 - 56.84 | 2.5 - 6.25 | 40.2 - 13.07 | 14.2 - 40.52 |
## [232. Implement Queue using Stacks.][232]
Only uses stack equivalent operations. Two lists are created, one that holds values
pushed and one that holds values that will be popped. When time comes to pop/peek,
we check to see if the list holding values to be popped is empty.
If it's emtpy, we continuously push the values popped from the other list (thereby
restoring the FIFO principle).
If it isn't empty, we immediatelly just pop/peek from it.
`is_empty` is `O(1)`. The rest are amortized `O(1)` operations (`push` definitely is,
at least. I'm relatively certain `peek` and `pop` are too).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 99.36 | 20 - 98.63 |
| Mem Usage (MB-%)| 5.8 - 96.97 | 1.9 - 100.00 | 38.4 - 67.68 | 14.1 - 98.99 |
## [237. Delete node in a Linked List][237]
Swap contents of `node` with contents of `node.next`. Rust version not
available.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 95.10 | N/A | 80 - 94.74 | 20 - 100.00 |
| Mem Usage (MB-%)| 6.3 - 99.87 | N/A | 40.2 - 84.74 | 14.7 - 19.26 |
## [240. Search a 2-d matrix II.][240]
Start from bottom left corner. Eliminate rows by checking if `target < row[0]` and columns by
checking if `target > row[0]`. (All values on the right of `target` if `target < row[0]` must be
larger while if `target > row[0]` columns to the right will contain larger values.)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 48 - 91.20 | 0 - 100.00 | 316 - 72.89 | 152 - 97.52 |
| Mem Usage (MB-%)| 9.1 - 92.00 | 2.5 - 78.95 | 41.7 - 81.98 | 20.4 - 97.73 |
## [242. Valid anagram.][242]
All except for C use a counter. No idea why `Rust` can't go lower than `4` though
I believe I could get it there with the same hack as in `C`.
Note: `C` case just seems hacky as hell, read comments (which do a pretty poor job
of explaining).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 4 - 61.40 | 84 - 95.92 | 28 - 99.36 |
| Mem Usage (MB-%)| 5.8 - 85.24 | 2.1 - 100.00 | 40.9 - 64.49 | 14.5 - 69.02 |
## [257. Binary Tree Paths,][257]
Recursively build path by holding (and passing) the partially constructed path
as an argument to the recursive function.
The path is added to the result once we reach a leaf.
Runtime complexity should be `O(N)` since we traverse each node. Space complexity
is related to the number of branches.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 99.71 | 24 - 97.96 |
| Mem Usage (MB-%)| 6.1 - 100.00 | 2 - 100.00 | 40.1 - 86.55 | 14 - 99.37 |
## [258. Add digits,][258]
This is one of those cases where you need to examine what the results are in order
to realize the solution. After running mucho input cases, notice that the result
is `num % 9` with special cases if `num == 0` and `num % 9 == 0`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 80 - 99.49 | 20 - 99.19 |
| Mem Usage (MB-%)| 5.7 - 39.50 | 2 - 100.00 | 39.9 - 84.01 | 14.2 - 36.59 |
## [263. Ugly Number.][263]
| Stats/Lang | C | Rust | Go | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 0 - 100.00 | 21 - 99.88 |
| Mem Usage (MB-%)| 5.4 - 97.68 | 2.1 - 61.11 | 2.1 - 6.30 | 14 - 12.36 |
## [268. Missing Number,][268]
Yet another variation of the xor trick. Since all numbers are in range `[0, n)` and
we know only one is missing, we can use another variable ranging from `[0, n)` and
xor it along with all the numbers in the numbers array.
Since numbers with the same value will be xored out, the missing number will be the
one left.
Runtime complexity is `O(N)`, space complexity is `O(1)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 16 - 92.23 | 0 - 100.00 | 80 - 91.77 | 120 - 96.29 |
| Mem Usage (MB-%)| 6.5 - 75.34 | 2 - 97.30 | 41.3 - 34.19 | 15.3 - 82.34 |
## [278. First bad version.][278]
Binary search, again.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 96.69 | 24 - 93.25 |
| Mem Usage (MB-%)| 5.5 - 53.47 | 2 - 81.08 | 38.4 - 45.85 | 14.1 - 73.36 |
## [283. Move zeroes.][283]
In order to minimize the comparisons made, our `run` variable always begins scanning
from the position in which a non-zero value was last found (which is zero in the
beginning). This way we only see each element in the nums array twice (once for the
`on_zero` variable tracking zeroes and once for the `run` variable tracking non-zero
values).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 100.00 | 0 - 100.00 | 76 - 98.15 | 32 - 99.97 |
| Mem Usage (MB-%)| 7.6 - 89.22 | 2.1 - 97.87 | 40.3 - 51.81 | 15.2 - 68.67 |
## [292. Nim Game,][292]
After some experimenting, we can see that the losing starting position is a multiple
of `4`. This makes sense, if we are on a multiple of `4`, our opponent can always
make the total stones decrease by `4` when playing optimally. This will lead to a
final count of `4` with us having to play and not being able to win the game.
In all other positions we can do the same, taking the correct ammount initially in
order to leave our opponent to make their first move with a number of rocks that is
a multiple of `4`.
Space/Time complexity is `O(1)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 89.79 | 20 - 98.68 |
| Mem Usage (MB-%)| 5.5 - 41.79 | 1.9 - 75.00 | 38.2 - 76.88 | 13.9 - 97.16 |
## [326. Powers of three.][326]
Similar to powers of two. Find `log3(n)` and then check how close `round(log3(n))` is to `log3(n)`. Powers of
three will have a value of `log3(n)` close to some integer `x`. I'm under the impression a better solution
exists but it is 4am and no.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 97.77 | 4 - 100.00 | 244 - 76.58 | 56 - 98.86 |
| Mem Usage (MB-%)| 6.5 - 13.41 | 2.6 - 5.00 | 49.4 - 43.63 | 14.4 - 13.70 |
## [338. Counting bits.][338]
Straight-forward dp solution. num of bits for `n` is equal to num of bits `n >> 1` plus one if the shifted
value was a `1`. We can use tabulation to hold the values and gradually fill it up. `O(N)` runtime.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 36 - 96.89 | 4 - 94.74 | 84 - 99.78 | 72 - 96.85 |
| Mem Usage (MB-%)| 10.4 - 86.65 | 2.4 - 100.00 | 44.5 - 77.83 | 20.9 - 40.74 |
## [342. Power of four.][342]
Exactly the same as Powers of three, only difference is that we use `log4(n)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 100.00 | 24 - 95.62 |
| Mem Usage (MB-%)| 5.9 - 12.62 | 2.7 - 5.56 | 40 - 36.68 | 14.3 - 6.03 |
## [344. Reverse String][344]
Typical swapping.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 44 - 96.89 | 16 - 94.12 | 100 - 96.48 | 184 - 96.43 |
| Mem Usage (MB-%)| 12.4 - 74.64 | 5.4 - 98.82 | 45.5 - 79.32 | 18.7 - 14.37 |
## [345. Reverse vowels of a string.][345]
Use `start` and `end` trackers and swap on encountering two vowels. Where mutating the
string is allowed (Rust, C), it's done. Overall `O(N)` runtime for all and `O(1)/O(N)`
for where we can mutate the string or not respectively.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 84 - 99.45 | 44 - 94.72 |
| Mem Usage (MB-%)| 6.5 - 100.00 | 2.5 - 90.91 | 43.2 - 99.59 | 15.1 - 71.47 |
## [347. Top k frequent elements.][347]
Counting + Building a k-element heap. Complexity of operation is `O(NlogK)` instead of
`O(NlogN)`. Python contains a built-in version of this `Counter.most_common` so Rust is
probably the best place to look for each of these steps layed out sequentially.
C: Not up for implementing my own binary heap (probably should and just keep it around).
Javascript: Priority Queue available seems somewhat broken to me? I can't seem to get it to
work for some reason.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | 0 - 100.00 | | 88 - 98.51 |
| Mem Usage (MB-%)| | 2.4 - 65.63 | | 18.7 - 76.49 |
## [349. Intersection of two arrays.][349]
Build sets and get intersection (or write it for `C` and `JS` cases.)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 98.18 | 32 - 99.40 |
| Mem Usage (MB-%)| 7.7 - 12.87 | 2.1 - 77.78 | 40.5 - 28.27 | 14.4 - 22.10 |
## [367. Valid perfect square.][367]
Use babylonian method to find a good approximation of the root and then check that
`approx * approx == num`. Using `root = pow(num, 0.5)` seemed like it was going against
the point.
Same notes as in problem 50 - Sqrt(x) apply.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 98.82 | 24 - 95.16 |
| Mem Usage (MB-%)| 5.4 - 64.94 | 1.9 - 81.82 | 38.8 - 12.48 | 14.4 - 6.53 |
## [374. Guess number higher or lower.][374]
Simple binary search for the number. `O(logn)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 88.26 | 20 - 98.89 |
| Mem Usage (MB-%)| 5.5 - 52.67 | 1.9 - 66.67 | 38.3 - 81.91 | 14.2 - 42.20 |
## [377. Combination sum IV.][377]
Tabulation solution looks magical, as always, so recursive solution in python file would probably
be a better place to start. Not sure about complexity, I'd need to think it through
longer (I should probably write a big list of DP problems I've solved.)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 95.04 | 28 - 99.28 |
| Mem Usage (MB-%)| 5.8 - 64.71 | 2 - 100.00 | 40.7 - 21.67 | 14.1 - 95.74 |
## [383. Ransom Note][383]
Use a counter to check that the required ammount of characters are present.
In C, Rust and JavaScript, an array of size 26 is filled up with the characters in the
magazine and then the characters from the ransom note are subtracted. If at any point
the value inside the array is zero, it means we've run out of characters.
Runtime complexity is `O(N + M)` where `N` and `M` are the sizes of the strings given.
Space complexity is `O(1)` since we only have 26 characters.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 80 - 99.57 | 40 - 86.90 |
| Mem Usage (MB-%)| 6.4 - 96.59 | 2.1 - 100.00 | 41.2 - 91.14 | 14.1 - 99.69 |
## [384. Shuffle an Array.][384]
Uses Fisher-Yates algorithm (the Durstenfeld's version) in order to shuffle sequence. This
leads to `O(N)` execution.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 212 - 82.28 | 24 - 100.00 | 228 - 89.90 | 264 - 89.11 |
| Mem Usage (MB-%)| 36.9 - 29.54 | 5.4 - 60.00 | 51.5 - 96.63 | 19.4 - 71.11 |
## [387. Find Unique Character in String.][387]
Build a Counter (in Python we use library supplied, in others, just use an array with
26 slots to act as Counter) and then go through characters of `s` and find the first
for which the count is equal to `1`.
Runtime complexity is `O(N)` for all, space is `O(1)` I believe since we always have
a collection with 26 elements regardless of string length.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 99.00 | 0 - 100.00 | 96 - 95.44 | 88 - 90.37 |
| Mem Usage (MB-%)| 6.9 - 80.90 | 2 - 78.26 | 42.4 - 58.18 | 14.4 - 70.26 |
## [389. Find the difference.][389]
Xor trick, different problem statement.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 98.01 | 28 - 92.43 |
| Mem Usage (MB-%)| 5.7 - 96.92 | 2 - 100.00 | 39 - 96.03 | 14.1 - 94.66 |
## [392. Is subsequence.][392]
Continuously search in the string `t` for the characters of `s`. Use bounds to not search
from the beginning for every char of `s` (and result in `O(nm)` complexity). `O(n)` time
complexity and `O(1)` space complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 95.25 | 24 - 95.69 |
| Mem Usage (MB-%)| 5.5 - 97.97 | 2 - 100.00 | 37.8 - 99.55 | 14.2 - 73.80 |
## [400. Nth digit.][400]
Pre-compute number of digits until `9, 99, 999, 9999, ..., 99999999` and store them
in an array. To find the k-th digit we then need to find where in that array `n` lies and
perform some simple arithmetic in order to find the number and digit that `n` denotes.
We grab the largest value in the array which is smaller than `n`. This sets our lower bound.
To find the number we just need to find out how many numbers are contained in `n - largest_value`
digits and what's left after that. That can be done with a pretty a simple divmod. All in all,
this is `O(1)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 95.83 | 12 - 100.00 |
| Mem Usage (MB-%)| 5.7 - 50.00 | 2 - 60.00 | 37.9 - 100.00 | 14.2 -41.10 |
## [404. Sum of left leaves.][404]
Relatively straight-forward, recurse on tree and while branching on the children
check if the left child is a leaf. If so, add its value, if not, recurse on it.
On right, we immediately recurse.
All solutions have used recursion, translating into stack based solution is easy.
This visits each node once, so `O(N)` time and space complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 99.26 | 28 - 89.99 |
| Mem Usage (MB-%)| 6.3 - 91.09 | 2.2 - 77.78 | 40.1 - 43.18 | 14.7 - 81.31 |
## [405. Convert a number to hexadecimal.][405]
Use a small table `[0, 1, 2, ..., 14, 15] => ['0', '1', '2', ..., 'e', 'f']` to translate between
the values from `[0-15]` to appropriate hex symbols. We manipulate the input number `n` in pairs of
`4`bits (`n & 15` and `n >> 4`) which we use to look up the value in the table.
To handle 2's complement (infinite 1's to the left), we simply bound the loop to generate a maximum of
`8` hex symbols.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 90.67 | 24 - 94.23 |
| Mem Usage (MB-%)| 5.4 - 85.25 | 2 - 100.00 | 38.4 - 90.67 | 14.3 - 11.14 |
## [409. Longest Palindrome.][409]
Build a counter out of the characters and then add all even counts and all odd minus one counts.
If we encounter an odd along the way, we add `1` (to be placed in the middle) to get longest
palindrome.
Runtime/memory complexity is `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 95.79 | 28 - 89.22 |
| Mem Usage (MB-%)| 5.7 - 100.00 | 2 - 80.00 | 39.6 - 82.30 | 14.2 - 81.53 |
## [412. Fizz-buzz.][412]
Straight-forward translation of statement, only trick is not performing `i % 3` and
`i % 5` twice do see if a number is a multiple of both `5` and `3`. We can use the
result of `i / 3` and see if that is divided by `5`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 69.37 | 0 - 100.00 | 76 - 96.82 | 34 - 92.74 |
| Mem Usage (MB-%)| 7 - 86.04 | 2.6 - 95.24 | 41.4 - 5.36 | 15 - 73.21 |
## [429. N-ary Tree Level Order Traversal.][429]
Similar to problem [Binary Tree Level Order Traversal][102]. The only difference being
that we know iterate through all children and add them to the stack. (implicit or explicit one.)
Complexity is the same, `O(N)` runtime/memory.
Rust: not available.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | N/A | 92 - 94.98 | 44 - 95.28 |
| Mem Usage (MB-%)| - | N/A | 43.7 - 26.96 | 16 - 87.08 |
## [434. Number of segments in a string.][434]
Split string on whitespace and filter empty items on resulting iterable. C needs to
manually step through the string. `O(N)` time (and space).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 95.61 | 20 - 98.30 |
| Mem Usage (MB-%)| 5.4 - 96.43 | 2 - 100.00 | 38.1 - 94.74 | 14.1 - 65.77 |
## [448. Find all numbers disappeared in an array.][448]
Couldn't see (yet) how to do it with `O(1)` space. For now, I use `O(N)` space
in the form of a vector or set in order to find disappeared numbers.
*TODO: Revisit but not urgently.*
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 92 - 98.94 | 8 - 98.04 | 96 - 99.71 | 312 - 99.29 |
| Mem Usage (MB-%)| 18.4 - 18.62 | 2.6 - 43.14 | 47.4 - 47.02 | 24.7 - 17.49 |
## [451. Sort characters by frequency.][451]
Count the characters, sort them by count, build the string.
The `O(N)` traversal of the string dominates the `O(klogk)` of the sort
due to the second being applied to an `k` which has a maximum value
of `count(letters + digits)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 88 - 92.53 | 24 - 99.90 |
| Mem Usage (MB-%)| 6.5 - 78.57 | 2.2 - 93.75 | 41.3 - 88.19 | 15.6 - 39.61 |
## [460. Minimum Changes to make alternating binary string.][460]
Need to count changes both version of alternating strings (`'010101..', '101010..'`). Call
a counting function that finds the counts for each of these cases and return the min value. Since
we only iterate through `s`, runtime complexity is `O(N)`. Space complexity is `O(1)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 92.66 | 40 - 92.84 |
| Mem Usage (MB-%)| 5.7 - 100.00 | 2 - 100.00 | 39.4 - 51.05 | 14.2 - 96.60 |
## [461. Hamming Distance][461]
Get the xor of the two numbers (where bits differ) and then
count set bits.
I'm under the impression I'm missing some other obvious
solution here.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 82.30 | 28 - 76.20 |
| Mem Usage (MB-%)| 5.5 - 67.52 | 2 - 100.00 | 38.5 - 71.22 | 14.1 - 61.18 |
## [476. Number Complement.][476]
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 76 - 85.35 | 24 - 94.21 |
| Mem Usage (MB-%)| 5.6 - 63.49 | 2 - 80.00 | 38.1 - 94.27 | 14 - 95.98 |
## [485. Max Consecutive Ones][485]
We have to scan the full array looking for the max consecutive number of ones. Runtime
complexity is `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 36 - 95.44 | 0 - 100.00 | 80 - 92.82 | 332 - 96.94 |
| Mem Usage (MB-%)| 7.4 - 97.54 | 2 - 85.71 | 41,6 - 32.50 | 14.3 - 92.44 |
## [495. Teemo attacking.][495]
Just iterate through the timeseries and the seconds as we go. `O(N)` time complexity
and `O(1)` space complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 28 - 100.00 | 4 - 100.00 | 72 - 100.00 | 240 - 93.39 |
| Mem Usage (MB-%)| 7.1 - 100.00 | 2.2 - 33.33 | 42.5 - 92.77 | 16.2 - 5.97 |
## [496. Next greater element I.][496]
Python has three solutions, brute force, with a bit of supporting structures and
with a lot. Last is used and in the others and described here.
We initialize the resulting array to all -1's and create a mapping from values to
their indices. We go through each element in `nums2` and for each:
1. If it is contained in our mapping, we add it to a set that keeps track of values
seen.
2. We iterate through the values of seen, if, for any value of seen, we find that
it is smaller than the element of `nums2` we're iterating through, we add it
to the result array (where we add it is found by using the mapping).
For any values not in `nums1` and for any values in `nums1` for which no larger
element exists on the right, the initial value of `-1` stays. The trick here is
that for each element of `nums2` we only iterate over a very small subset of
`nums1` (the ones in `seen`). This way we can reduce the overall iterations
performed.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 76 - 97.12 | 36 - 98.72 |
| Mem Usage (MB-%)| 10.4 - 6.67 | 2 - 100.00 | 40.5 - 42.45 | 14.6 - 18.78 |
## [500. Keyboard Row][500]
Make sets out of rows on keyboard and check if input strings are contained
in the sets.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 97.03 | 24 - 92.53 |
| Mem Usage (MB-%)| 5.8 - 20.69 | 2 - 100.00 | 38.6 - 33.83 | 14.1 - 44.11 |
## [504. Base 7.][504]
Find the digits by continuously taking `num mod 7` and reducing `num` by `/ 7`. This is done on
the absolute value of the number, the sign is removed and its presence is tracked in a boolean flag.
After that, we only need to build the resulting string.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 99.32 | 24 - 95.12 |
| Mem Usage (MB-%)| 5.6 - 75.00 | 2 - 85.71 | 39.3 - 6.12 | 14.3 - 43.06 |
## [509. Fibonacci Number][509]
Calculate it iteratively.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 97.37 | 20 - 98.15 |
| Mem Usage (MB-%)| 5.4 - 86.96 | 2 - 48.78 | 38.3 - 56.54 | 14.1 - 34.89 |
## [515. Find largest value in each tree row.][515]
Straight-forward. Keep an array of maxes and recurse/iterate while holding on to
a variable denoting the level. Update the maxes array using that level. Uses DFS and
visits all nodes. `O(N)` space and time complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 80 - 98.94 | 40 - 93.53 |
| Mem Usage (MB-%)| 14.7 - 8.33 | 3 - 100.00 | 44.2 - 8.80 | 16.5 - 57.81 |
## [520. Detect Capital.][520]
We can just check the second character and disambiguate which case we're examining.
Then we just make sure all the following characters match the case.
`O(N)` runtime complexity with `O(1)` space complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 100.00 | 20 - 98.83 |
| Mem Usage (MB-%)| 5.5 - 98.33 | 2 - 60.00 | 39.8 - 81.21 | 14.2 - 48.87 |
## [521. Longest Uncommon Subsequence.][521]
If the strings are equal, all subsequences are the same, return -1.
Else, return the largest among the strings.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 95.35 | 24 - 93.63 |
| Mem Usage (MB-%)| 5.4 - 100.00 | 2 - 100.00 | 38.4 - 61.63 | 14 - 98.24 |
## [530. Minimum absolute difference in bst.][530]
C and Rust both traverse the bst and build a sorted vector. Python and Javascript
use a generator to yield back values. Whatever the case, we then traverse through
the value and find the minimum.
Note: Javascript would probably be faster if I didn't use generators. Problem is,
I really like generators so I don't care.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 97.44 | 0 - 100.00 | 128 - 14.84 | 48 - 96.33 |
| Mem Usage (MB-%)| 10.8 - 20.51 | 2.9 - 25.00 | 46.2 - 9.03 | 16.3 - 32.45 |
## [535. Encode and Decode TinyURL.][535]
As basic as it gets implementation. (Note: just returning the string as-is actually
works, they don't test to guard against this).
There's an issue with Rust in that the test code declares the coder as immutable
thereby not allowing us to pass it mutably by reference.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | N/A | 84 - 93.40 | 24 - 97.30 |
| Mem Usage (MB-%)| | N/A | 40 - 83.96 | 14.2 - 58.76 |
## [538. Convert BST to Greater Tree][538]
Code used is exactly the same for [Binary Search Tree to Greater Sum Tree](1038).
As such, see `1038.*` files for the code.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 16 - 92.86 | 0 - 100.00 | 100 - 100.00 | 72 - 98.64 |
| Mem Usage (MB-%)| 13.7 - 100.00 | 2.9 - 83.33 | 47.7 - 28.72 | 16.7 - 80.07 |
## [539. Minimum Time Difference.][539]
Idea is transform times into a continuous range of ints (i.e 0 - 1440) by multiplying hours
by `60`. After doing that we can go through transformed values and find minimum. Since time wraps
around we need to check if the maximum value and the minimum value are closer than the minimum found
after traversing array.
Using a set to check for duplicates (and return early if one is found) appears to be a good optimization.
Overall, this uses `O(N)` additional space and runs in `O(NlogN)` due to the sorting.
Note for C: This can easily be translated there. Dealing with sets is a pain though and I'm not into it
anymore.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | 0 - 100.00 | 84 - 99.11 | 52 - 99.37 |
| Mem Usage (MB-%)| | 3.1 - 100.00 | 41.6 - 62.83 | 16.9 - 92.87 |
## [547. Number of provinces.][547]
Dfs on nodes. Adjacency matrix representation doesn't help at all with this but meh. We still traverse
O(V**2) times.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 24 - 80.00 | 0 - 100.00 | 72 - 97.31 | 180 - 91.43 |
| Mem Usage (MB-%)| 7 - 50.00 | 2.1 - 100.00 | 39.9 - 98.59 | 14.7 - 72.30 |
## [551. Student Attendance Record I.][551]
Iterate through characters with two counters. One counts occurences of `A`s and returns
if the count reaches `2`. The second counts consecutive occurences of `L`s and returns if
it equals `3`. Overall, `O(N)` runtime and `O(1)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 93.62 | 20 - 99.19 |
| Mem Usage (MB-%)| 5.5 - 73.81 | 2 - 77.78 | 38.8 - 41.49 | 14 - 90.13 |
## [557. Reverse Words in a String III][561]
C mutates the string in-place because it's allowable there.
The rest split on `' '`, iterate through the chunks and
reverse them.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 93.81 | 0 - 100.00 | 88 - 74.93 | 24 - 97.41 |
| Mem Usage (MB-%)| 6.9 - 72.57 | 2.3 - 72.73 | 44.6 - 85.18 | 14.6 - 84.18 |
## [559. Maximum depth of N-Ary Tree][559]
Common recursive approach (call depth on all children.)
Note: For some reason, `maxDepth` in `C` is defined as returning `int *`.
Note: Rust case not applicable, they don't allow the option yet.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | N/A | 84 - 95.55 | 40 - 91.04 |
| Mem Usage (MB-%)| 7.3 - 8.70 | N/A | 42.1 - 33.27 | 16.2 - 7.06 |
## [561. Array Partition I][561]
Sort the array in reverse order and sum every second
element.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 52 - 80.25 | 8 - 96.15 | 120 - 93.30 | 244 - 97.34 |
| Mem Usage (MB-%)| 8.5 - 27.16 | 2.2 - 100.00 | 44 - 79.12 | 16.5 - 81.43 |
## [566. Reshape the matrix.][566]
Check that new dimensions can hold elements and then go through each
element in `nums` and place it in new position based on `r` and `c`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 36 - 100.00 | 0 - 100.00 | 96 - 96.50 | 84 - 99.31 |
| Mem Usage (MB-%)| 11.4 - 100.00 | 2.3 - 100.00 | 44.6 - 51.05 | 15.2 - 59.61 |
## [572. Subtree of another tree.][572]
Traverse tree until a node with value equal to `subRoot.val` is encountered. Then check if
subtrees match using recursion. This could probably be improved by building a list of the
`subRoot` values and checking the nodes against that.
Rust: Need to come back to this, refcells with references are still difficult for me.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 99.17 | - | 92 - 98.19 | 132 - 81.28 |
| Mem Usage (MB-%)| 10.9 - 98.33 | - | 44.9 - 90.86 | 15 - 88.52 |
## [575. Distribute Candies][575]
Use a set and compare its size with the ammount prescribed (Goes south for `C`
though, which might mean there's a different better way at it.)
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 224 - 21.43 | 24 - 100.00 | 128 - 90.75 | 764 - 92.56 |
| Mem Usage (MB-%)| 68.3 - 7.14 | 2.2 - 86.67 | 52.7 - 35.24 | 16.5 - 8.60 |
## [589. N-Ary tree pre-order traversal][589]
Option for Rust isn't available yet unfortunately.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 82.00 | N/A | 92 - 89.63 | 48 - 81.31 |
| Mem Usage (MB-%)| 19.9 - 24.00 | N/A | 43.1 - 13.39 | 15.6 - 86.89 |
## [590. N-Ary tree post order traversal][590]
All using iterative versions (probably partly explains why
timings show sluggishness).
Option for Rust isn't available yet unfortunately.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 20 - 14.63 | N/A | 100 - 55.56 | 32 - 100.00 |
| Mem Usage (MB-%)| 24.4 - 9.76 | N/A | 43.7 - 9.69 | 15.8 - 57.01 |
## [605. Can place flowers.][605]
In short, we need to go through the array in three pairs `i-1, i, i+1` and check
if we can place a flower there. Main trick we can utilize is to increment `i` by
more than one in specific cases.
See Python file for step by step comments on what is done. Overall, `O(N)` (eh, `N/2`)
in the worse case.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 98.04 | 0 - 100.00 | 80 - 90.99 | 148 - 99.49 |
| Mem Usage (MB-%)| 7 - 100.00 | 2.1 - 100.00 | 40.5 - 79.19 | 14.6 - 70.07 |
## [606. Construct string from binary tree.][606]
Preorder traversal through the tree and build the string. If we don't have a left
subchild but do have a right one, we need to add the extra `'()'` as stated in
the problem statement.
For C, couldn't be buggered, really. Need to recurse through the tree with a
pointer to `char *` array and add things to it. Then, join them all together
at the end. Might do some point in the future, for now, nope.
Time complexity is `O(N)`, space complexity is probably the same.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 0 - 100.00 | 84 - 97.62 | 40 - 98.24 |
| Mem Usage (MB-%)| - | 3.1 - 100.00 | 48.6 - 5.56 | 16.5 - 10.29 |
## [617. Merge Two Binary Trees][617]
Don't recurse. Breadth first traversal using a queue.
Add branches immediately when we can.
Pending:
- `C` because I need to make a small queue first.
- `Rust`: Got to sit down and learn `Rc`s and `RefCell`s better. [OK, more familiar now].
- `Javascript`: File added, timings need to improve.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | 4 - 100.00 | | 80 - 96.68 |
| Mem Usage (MB-%)| | 2.2 - 100.00 | | 14.9 - 99.93 |
## [637. Average of Levels in Binary Tree][637]
Python, Rust use iterative approach: we use a deque that holds a special
marker (i.e `None`) which we use to track on which level we are on. Until we
reach that marker, we add the values and count the nodes. When we reach the
marker, we take the average and add it to the result array.
The iteration stops when for a given level, the number of Nodes we've counted
is zero.
`C` and `Javascript` use a recursive approach whereby each level of the tree
is represented by a `level` parameter of the recursive function.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 84 - 97.80 | 36 - 99.85 |
| Mem Usage (MB-%)| 20.7 - 5.36 | 3 - 50.00 | 45 - 18.13 | 16.5 - 60.71 |
## [641. Design Circular Deque.][641]
Two common approaches for this: a doubly linked list (see Python) or a circular
buffer/list (see C/Rust/Javascript). The main difference is in memory requirements since
a doubly linked list needs to store references to front/back for all nodes.
All in all, memory footprint for both is `O(N)` and both display `O(1)` complexity for
all operations.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 20 - 100.00 | 4 - 100.00 | 104 - 100.00 | 64 - 91.50 |
| Mem Usage (MB-%)| 12.5 - 80.00 | 2.4 - 66.67 | 45.9 - 77.14 | 15.1 - 43.28 |
## [643. Maximum average subarray I.][643]
`O(N)`, the main thing to notice (I believe) is the fact that you do not need to calculate the
full summation for the average each time (k terms added and divided by k). Instead, you can build
the summation until `k` and then move along the array looking for the max. At the end of each loop
we remove the first term of the summation and add the term we've currently looked at.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 100 - 100.00 | 12 - 100.00 | 92 - 97.89 | 780 - 96.34 |
| Mem Usage (MB-%)| 10.5 - 50.75 | 2.4 - 33.33 | 47.9 - 37.19 | 18.1 - 10.88 |
## [645. Set Mismatch.][645]
My solution is in Python where a Set and the sum until `n` is used in order to find these.
Did peek at solution that plays around with the indices and sets them to negatives. This is a solid
trick to remember whenever dealing with arrays holding sequences that can be used to index it (or
holding sequences of values that can be transformed into the range `0..array.len()`).
First approach with Sets uses `O(n)` runtime complexity and `O(n)` space. Second approach uses two
iterations but `O(1)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 20 - 97.47 | 0 - 100.00 | 84 - 94.77 | 192 - 71.13 |
| Mem Usage (MB-%)| 7.1 - 79.75| 2.1 - 100.00 | 42.2 - 68.11 | 15.2 - 97.92 |
## [653. Two Sum IV - Input is a BST.][653]
Use a set to hold the values and traverse tree. For each node see if `k - node.value`
is present inside the set, if so, done.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 98.11 | 0 - 100.00 | 104 - 97.44 | 68 - 97.46 |
| Mem Usage (MB-%)| 25.6 - 18.87 | 3.3 - 80.00 | 48.7 - 22.16 | 16.3 - 94.07 |
## [654. Maximum Binary Tree.][654]
Work with ranges. Start by calling recursive function in full range. Find max and its
index in the nums array and then recurse on `[start, id_max]` for the left subtree
and `[id_max + 1, end]` for the right subtree.
Create node and return.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 36 - 98.11 | 8 - 100.00 | 108 - 96.08 | 192 - 88.87 |
| Mem Usage (MB-%)| 26.9 - 90.57 | 2.1 - 100.00 | 45.1 - 77.94 | 15.1 - 8.05 |
## [657. Robot Return to Origin][657]
Count occurences and compare. If number of 'D's matches number
of 'U's and number of 'L's matches number of 'R's, we're good.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 95.76 | 0 - 100.00 | 80 - 90.34 | 32 - 94.10 |
| Mem Usage (MB-%)| 6 - 57.63 | 1.9 - 100.00 | 39.7 - 61.54 | 14.2 - 67.31 |
## [669. Trim a binary Search Tree.][669]
Initially we need to see where our root value lies. If it isn't inside the
acceptable range, we need to adjust it until it is. This is done by setting
the root to right or left depending if the value of root is smaller than
`low` or larger than `high` respectively.
After we have found a new root, we continuously recurse on children and, by
keeping a reference to their parent, trim any node not inside the range by
re-assigning pointers/attributes. Recursion is terminated when we reach
all leaves.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 76.47 | 0 - 100.00 | 88 - 86.70 | 40 - 97.47 |
| Mem Usage (MB-%)| 10.6 - 64.71 | 2.9 - 87.50 | 44.2 - 83.74 | 14.1 - 46.08 |
## [674. Longest continuous increasing subsequence.][674]
Iterate through array and keep track of longest sequence encountered. `O(N)` runtime
and `O(1)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 76 - 87.79 | 68 - 93.20 |
| Mem Usage (MB-%)| 6.4 - 65.67 | 2.3 - 80.00 | 39 - 95.35 | 15.4 - 57.78 |
## [680. Valid Palindrome II.][680]
Start typically by comparing characters via two counters, start and end. When a different character
is encountered, compare the substrings `s[start+1:end]` and its reverse, if that isn't
equal compare `s[start:end-1]` with its reverse. Essentially, skip the character for the two cases
that appear (either from start, or from end). Overall, `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 16 - 91.53 | 0 - 100.00 | 13 - 96.03 | 94 - 97.78 |
| Mem Usage (MB-%)| 9.3 - 33.90 | 2.4 - 34.48 | 10 - 5.05 | 14.5 - 49.54 |
## [682. Baseball Game][682]
While loop your way through the operations, make sure you skip performing an
operation if it is followed by a `"C"`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 92.51 | 32 - 96.73|
| Mem Usage (MB-%)| 6.2 - 55.17 | 2.1 - 100.00 | 38.9 - 90.64 | 14.4 - 53.20 |
## [684. Reduntant Connection.][684]
Use a disjoint set union structure and track cycles (where `find(a) == find(b)`). Iterate
through all edges and hold on to the last one that would create a cycle. Overall, this
runs in `O(E)` and has memory requirements of the same order.
Alternatively, we could transform into adjacency list representation, run dfs and
check for back-edges. Since we get and edge list, the union-find solution is
probably better.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 76 - 93.97 | 52 - 88.08 |
| Mem Usage (MB-%)| 6.2 - 61.06 | 2.1 - 89.47 | 40.8 - 80.98 | 14.7 - 95.83 |
## [690. Employee Importance][690]
Transform employees into a dictionary keyed by the id. Then we can build a list of
all subordinates by continuously keying the dictionary and build up the overall
importance.
*NOTE: Rust and C versions not available.*
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| N/A | N/A | 80 - 97.80 | 144 - 98.93 |
| Mem Usage (MB-%)| N/A | N/A | 44.2 - 17.56 | 15.5 - 53.57 |
## [693. Binary Number with alternating bits.][693]
Check adjacent bits until we reach end. If at any point a pair of adjacent bits is the
same, return False.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 95.92 | 20 - 99.27 |
| Mem Usage (MB-%)| 5.5 - 55.67 | 1.9 - 66.67 | 38.6 - 53.06 | 14.4 - 5.57 |
## [696. Count binary substrings.][696]
Go through each character and build count of adjacent groups by using a couple
of flags. Count of adjacent groups can then be found easily.
Note: Rust :(
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 93.75 | 4 - 60.00 | 84 - 93.42 | 112 - 96.53 |
| Mem Usage (MB-%)| 6.7 - 100.00 | 2 - 100.00 | 41.8 - 92.11 | 14.5 - 88.91 |
## [697. Degree of an Array.][697]
Build a counter of the numbers in the array in order to find the maximum degree
along with which numbers have that maximum degree.
After that we can iterate through the numbers array from the left (start) and
right (end) and look for the leftmost and rightmost occurences for each of the
numbers that has that maximum degree.
The minimum difference `end - start` for each of the numbers with max degree is
the result.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 20 - 100.00 | 4 - 100.00 | 84 - 98.22 | 196 - 99.93 |
| Mem Usage (MB-%)| 9.8 - 22.22 | 2.2 - 100.00 | 44.5 - 36.89 | 15.2 - 98.41 |
## [700. Search in a BST][700]
Straight-forward. Perform binary search. `C` code also contains
a tail-recursive version, didn't seem to make much difference
in runtime/memory timings.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 20 - 89.04 | 4 - 100.00 | 44 - 98.93 | 64 - 97.56|
| Mem Usage (MB-%)| 15.1 - 73.25 | 2.6 - 57.14 | 44.4 - 76.63 | 15.8 - 94.95|
## [704. Binary Search.][704]
Well, binary search. `O(logn)` complexity, `O(1)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 28 - 98.79 | 0 - 100.00 | 76 - 92.07 | 216 - 99.84 |
| Mem Usage (MB-%)| 6.9 - 99.19 | 2.1 - 100.00 | 42.4 - 52.53 | 15.5 - 91.95 |
## [705. Design HashSet][705]
Python contains implementations for both separate chaining and open addressing, so
does `Rust` (well, an attempt at separate chaining, at least).
Have some odd bug in Javascript which I'll give up on trying to track down for now.
Adding code so far.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 76 - 100.00 | 16 - 100.00 | N/A | 196 - 57.80 |
| Mem Usage (MB-%)| 26.1 - 96.83 | 5.6 - 66 | N/A | 18.9 - 53.31 |
## [709. To lower case][709]
The `C` version is probably the most interesting. The rest
just use the language provided conversion methods.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 53.05 | 20 - 97.94|
| Mem Usage (MB-%)| 5.7 - 20.65 | 2 - 100.00 | 38.4 - 8.75 |14.1 - 99.88|
## [728. Self Dividing Numbers][728]
Go through digits of number and check for divisibility. Basically
brute-forcing our way to an answer. Not sure if anything better
than brute-force is possible.
Sidenote: Transforming to strings could be a better approach,
not sure.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 84 - 65.67 | 44 - 81.10 |
| Mem Usage (MB-%)| 6.2 - 14.75 | 2.2 - 100.00 | 38.8 - 11.69 | 14.1 - 100.00 |
## [744. Find smallest letter greater than target.][744]
We can immediately handle the wrap-around case by checking if `target` is `>=` than
the last element in the sorted vector. If that is the case, we immediately return the
first element.
If not, just traverse the array and find the character.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 96.63 | 100 - 94.06 |
| Mem Usage (MB-%)| 6 - 64.29 | 2.7 - 40.00 | 41.2 - 12.36 | 14.3 - 84.93 |
## [746. Min cost climbing stairs.][746]
Dynamic Programming with tabulation. Solutions for step `n` is the minimum between the solutions at
one step `n-1` and the two steps `n-2` back, plus the cost of the step at `n`.
`O(N)` runtime and space complexity.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 97.35 | 48 - 97.19 |
| Mem Usage (MB-%)| 5.9 - 60.49 | 0 - 100.00 | 39.8 - 56.16 | 14.1 - 99.68 |
## [748. Shortest completing word][748]
To be frank, don't think things are good here. Might need to place this problem in
the revisited section. I won't much bother with `C` with the current solution that
uses a host of maps/sets.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | 4 - 66.67 | 96 - 75.76 | 60 - 97.43 |
| Mem Usage (MB-%)| | 2.1 - 66.67 | 43.7 - 51.51 | 14.6 - 24.70 |
## [766. Toeplitz Matrix][766]
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 98.44 | 0 - 100.00 | 84 - 91.64 | 80 - 86.38 |
| Mem Usage (MB-%)| 6 - 98.44 | 2 - 75.00 | 40.5 - 40.68 | 14.1 - 90.26 |
## [771. Jewels and Stones][771]
Add the values of J to a set and count number of jewels by
using the set membership test to quickly establish if a
character is a jewel.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 80 - 73.22 | 24 - 93.75 |
| Mem Usage (MB-%)| 5.8 - 25.51 | 2.1 - 100.00 | 40.4 - 11.66 |14.2 - 99.99 |
## [783. Minimum Distance between bst nodes.][783]
Same as problem [530. Minimum absolute difference in bst][530], see there.
## [788. Rotated Digits][788]
I'll probably need to write this up in a separate `.md` file. Until then,
see the source code for the Python case where I prototyped and added
most comments.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 80 - 94.16 | 20 - 99.86 |
| Mem Usage (MB-%)| 5.7 - 45.71 | 2 - 66.67 | 38 - 100.00 | 14.1 - 90.83 |
## [797. All paths from source to target.][797]
Perform a dfs without tracking visited nodes. Since we have a DAG, we needn't worry about
recursing infinitely. We just need to incrementally build a path indicating our current
visit from the source and keep track of it when we encounter our destination.
Python contains both recursive and iterative, Rust and Javascript contain iterative. C is
similar but, once again, manual memory allocation.
This follows every single edge so it should be `O(E)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 8 - 100.00 | 100 - 97.30 | 92 - 96.32 |
| Mem Usage (MB-%)| - | 2.7 - 100.00 | 46.6 - 52.13 | 15.5 - 91.83 |
## [804. Unique Morse Code Words.][804]
Build the morse code words and add them to a set. After adding
all words just return the length of the, now, unique set of
morse code words.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 86.43 | 24 - 99.14|
| Mem usage (mb-%)| 6.1 - 13.33 | 2 - 100.00 | 39.4 - 6.79 | 14.1 - 100.00 |
## [806. Number of lines to write string.][806]
Build a mapping from lowercase english characters to their width in the `widths`
array. Then, gradually find the lines needed.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 76 - 90.28 | 20 - 99.40 |
| Mem usage (mb-%)| 5.8 - 44.44 | 2 - 66.67 | 39.4 - 12.50 | 14.2 - 48.64 |
## [807. Max increase to keep city skyline.][807]
Max ammount that we can grow is `min(max_of_row, max_of_col)`. We can just find
these values and compute the maximum increase.
Pretty sure complexity is around `O(N*M)`, inner loop computing maximum for column only
runs once per column, this means that we have a significant lower term in our
complexity equation.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 93.02 | 0 - 100.00 | 80 - 91.76 | 64 - 96.36 |
| Mem usage (mb-%)| 6 - 97.67 | 2.1 - 86.67 | 39.1 - 92.86 | 14.3 - 61.22 |
## [811. Subdomain visit count.][811]
Hold domains/subdomains in a Counter and count values after
splitting domain up.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 16 - 71.43 | 4 - 100.00 | 92 - 93.28 | 44 - 95.94|
| Mem usage (mb-%)| 9.6 - 28.57 | 2.2 - 25.00 | 43.4 - 70.71 | 14.4 - 26.05 |
## [812. Largest Triangle Area.][812]
Initially I tried to see if we can skip taking all combinations by trying to find
two points that are maximally appart and using those as the two initial points.
Unfortunately, this isn't correct.
After this I tried using Heron's formula to find the area based on the length of the
sides of the trianges (found using Euclidean distance). While working, this wasn't
very efficient.
Thankfully, after some digging around was able to find the Shoelace formula which made
my life easier because I only uses the three points of the triangle to calculate the
area.
Still, algorithm is dominated by the fact that we have to go through all combinations
(and I can't think of a way to reduce the iteration space).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 87.50 | 0 - 100.00 | 80 - 93.33 | 96 - 94.12 |
| Mem usage (mb-%)| 5.8 - 100.00 | 2 - 100.00 | 39 - 60.00 | 14.3 - 48.90 |
## [821. Shortest Distance to a Character.][821]
By keeping around the positions the character is found and the previous position
found, we can easily build the ranges after taking care of some special
cases.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 100.00 | 0 - 100.00 | 76 - 99.41 | 28 - 98.30 |
| Mem usage (mb-%)| 6 - 100.00 | 2 - 100.00 | 41 - 28.99 | 14.1 - 97.67 |
## [824. Goat Latin.][824]
Not much to break down here. Just do what the problem states.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 94.85 | 24 - 93.52 |
| Mem usage (mb-%)| 5.9 - 84.21 | 2 - 87.50 | 38.8 - 59.56 | 13.9 - 97.34 |
## [832. Flipping an Image][832]
Go through matrix and reverse/invert. Python/Rust/JS use a functional
approach. C iterates through elements.
**TODO: Write version for C where pointer arithmetic is used.**
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 67.03 | 0 - 100.00 | 80 - 86.11 | 40 - 99.08|
| Mem usage (mb-%)| 7.2 - 72.54 | 2.1 - 100.00 | 40.2 - 18.30 | 13.9 - 100.00 |
## [841. Keys and rooms.][841]
DFS from room zero and check if we can reach all rooms (# of visited == # of rooms). `O(N)` space and runtime
where `N` is total number of rooms.
Note: C is the same, manual allocation makes me too bored to implement now.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| - | 0 - 100.00 | 76 - 91.87 | 60 - 92.21 |
| Mem usage (mb-%)| - | 2.1 - 100.00 | 40.2 - 79.95 | 14.8 - 81.62 |
## [845. Longest Mountain in Array.][845]
Step through array and attempt to perform an up-down motion through the values. We need
at least one up and one down step in order to register a mountain, in other situations we
don't have one.
When we find a mountain we advance the counter by the number of `up + down - 1` steps performed. This way
we can check if the end of the `down` part of a mountain starts the `up` part of another mountain.
This uses no extra storage and performs `O(N)` loops.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 100.00 | 0 - 100.00 | 64 - 100.00 | 156 - 94.06 |
| Mem usage (mb-%)| 6.6 - 90.91 | 2.1 - 100.00 | 41.1 - 40.82 | 15.1 - 99.73 |
## [852. Peak index in a Mountain Array.][852]
A binary search throug the semi-sorted array.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 89.84 | 0 - 100.00 | 72 - 91.56 | 64 - 97.11 |
| Mem usage (mb-%)| 6.6 - 30.47 | 2.1 - 75.00 | 39.1 - 77.91 | 15 - 88.20 |
## [859. Buddy strings.][859]
See comments in python file (`859.py`) for a better description. `O(N)` execution.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 64 - 100.00 | 24 - 98.49 |
| Mem usage (mb-%)| 5.7 - 56.92 | 2.2 - 81.82 | 41.2 - 35.74 | 14.5 - 71.61 |
## [867. Transpose Matrix.][867]
Straight-forward transpose.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 24 - 97.44 | 0 - 100.00 | 80 - 97.45 | 68 - 96.25 |
| Mem usage (mb-%)| 10.1 - 20.51 | 2.2 - 50.00 | 40.7 - 79.27 | 14.9 - 44.26 |
## [868. Binary Gap.][868]
Go through each bit of `n` (via `n >>= 1`) and count the distance between
two ones.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 97.12 | 20 - 98.78 |
| Mem usage (mb-%)| 5.6 - 46.88 | 2 - 100.00 | 38.8 - 50.00 | 14.2 - 57.69 |
## [872. Leaf similar trees.][872]
For Python: recursion delegating to sub-generators. Helpful.
For the rest: function that receives stack and returns leaves as we encounter
them.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 97.33 | 20 - 99.00 |
| Mem usage (mb-%)| 6.3 - 90.20 | 2 - 66.67 | 40.3 - 73.66 | 14.3 - 17.11 |
## [876. Middle of the Linked List][876]
Traverse the list while keeping a reference to the middle element.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 89.27 | 20 - 98.87 |
| Mem usage (mb-%)| 5.8 - 68.20 | 2 - 80.00 | 38.2 - 89.15 | 14 - 73.76 |
## [883. Projection Area of 3d Shapes][883]
Length of rows is the same.
View from Z axis is simply a count of all non-zero values.
View from X axis is the max of each row/cell.
View from Y axis is the max of each column.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 100.00 | 0 - 100.00 | 68 - 100.00 | 60 - 97.64 |
| Mem usage (mb-%)| 6 - 100.00 | 2 - 50.00 | 39 - 58.82 | 14.1 - 77.88 |
## [884. Uncommon words from two sentences.][884]
Create two sets for each String, a set of seen words and a set of words
unique in each String.
Then we take the difference of the unique words in string `A` and the
seen words in `B` (to only keep unique words not in the other string). We
do the same thing for the unique words of `B`.
Then we can take their union.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 96.65 | 24 - 94.61|
| Mem usage (mb-%)| 7.3 - 16.67 | 2.1 - 66.67 | 39.1 - 33.97 | 14.1 - 88.96 |
## [888. Fair Candy Swap.][888]
Brute force approach is going through each pair and checking.
A sligtly better option is to filter values based on if they bring us in the right
range (which can be found by adding the sums and dividing by two).
The best approach in the end is to use a set for one of the arrays. Then, knowing what
the difference between the two sums is in the beginning, we can go through the elements
of one array and find what the value should be in order to fill the difference between
the initial sums. If the value found is inside the set created for the other array, we've
found our element (which is guaranteed to exist).
**NOTE: C timings indicate either that uthash is slow or that a better option exists
that I haven't seen yet.**
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 88 - 48.16 | 8 - 100.00 | 100 - 97.93 | 332 - 99.56 |
| Mem usage (mb-%)| 26.6 - 11.11 | 2.5 - 100.00 | 48.1 - 28.28 | 16.6 - 41.79 |
## [896. Monotonic Array.][896]
Note that equal elements can't be ignored.
Find first non-equal pair in array, this initializes a flag that indicates the
direction the rest of the elements should be in in order for the array to be
monotonic. As soon as a pair isn't in the right direction, return `false`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 56 - 94.29 | 4 - 100.00 | 88 - 93.66 | 448 - 91.01 |
| Mem usage (mb-%)| 9.4 - 100.00 | 2.4 - 92.31 | 45 - 61.09 | 20.5 - 53.08 |
## [897. Increasing Order Search Tree][897]
Inorder traversal to gather nodes and then re-attaching
accordingly.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 68 - 98.18 | 24 - 94.91|
| Mem usage (mb-%)| 6.2 - 59.26 | 2.2 - 100.00 | 38.9 - 61.82 | 14 - 77.72 |
## [905. Sort Array By Parity.][905]
The two ways I've done this is either by simply sorting with the
appropriate key function or by using a deque.
Sorting takes `O(nlogn)` and `O(1)` space while using a deque
results in `O(n)` runtime complexity and `O(n)` space.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 28 - 77.42 | 0 - 100.00 | 96 - 72.31 | 60 - 99.98|
| Mem Usage (MB-%)| 9.3 - 97.35 | 2.1 - 100.00 | 40.6 - 10.20 | 14.6 - 36.39|
## [908. Smallest Range I.][908]
Find min and max of the array. IF `max - K - min` falls in the range `[-K, K]` we
can use any value of that range to reduce the difference to `0`. If it doesn't,
then, if `max - K - min` is positive, subtract `K` from it (to minimize the
difference) or, if negative, add `K` to it.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 12 - 88.89 | 0 - 100.00 | 72 - 96.74 | 96 - 100.00 |
| Mem Usage (MB-%)| 6.5 - 100.00 | 2 - 100.00 | 39.8 - 85.87 | 15.2 - 97.14 |
## [917. Reverse only letters.][917]
Code was written very quickly. Uses a set of acceptable characters and only switches when
we are on a valid pair of characters (in ascii letter range).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 0 - 100.00 | 0 - 100.00 | 72 - 94.95 | 24 - 95.12 |
| Mem Usage (MB-%)| 5.9 - 26.32 | 2 - 50.00 | 38.9 - 51.51 | 14.4 - 12.88 |
## [922. Sort Array By Parity II][922]
Preallocate resulting array. Then go through input array and using two
variables to denote the positions of the odds and evens, fill the
array.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 64 - 93.81 | 8 - 100.00 | 88 - 100.00 | 196 - 92.39 |
| Mem Usage (MB-%)| 13.5 - 51.55 | 2.1 - 77.78 | 44.4 - 74.18 | 16.8 - 15.40 |
## [929. Unique Email Address.][929]
Either step through the characters directly (see `C` and `Python` and `Rust` files)
or use string facilities that do that for you (see `Python` and `Javascript`).
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 8 - 98.31 | 0 - 100.00 | 88 - 91.97 | 44 - 91.99 |
| Mem Usage (MB-%)| 8.1 - 10.17 | 2.1 - 93.33 | 44 - 41.89 | 14.4 - 7.90 |
## [933. Number of Recent Calls][933]
Keep t's in a Queue/Deque and using that find the correct
amount of pings. Keeping the last ping around in a
separate variable allows us to quickly answer with 1 and
clear the Queue/Deque.
**TODO: Need to implement a Queue for C for it to run. Code
is currently written as if using a Queue.**
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| | 32 - 94.22 | 228 - 72.72 | 260 - 99.58 |
| Mem Usage (MB-%)| | 5.6 - 84.39 | 50.2 - 29.84 | 18.7 - 91.13|
## [937. Reorder Data in log files.][937]
Separate into two arrays, one containing the logs that only have digits after the
identifier and one with the rest (containing letters).
The digits array doesn't need any processing.
The letters array is sorted based on the string after the identifier and, if they
compare equal, the identifier is used as a tie-braker (see C version for clear
illustration of this).
Splitting the arrays is `O(N)` while sorting the letters is `O(logM)` where `M`
is the total number of rows in the logs array that are letter based. Auxiliary
memory is `O(N)`.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 4 - 90.00 | 0 - 100.00 | 80 - 95.48 | 28 - 97.50 |
| Mem Usage (MB-%)| 7.6 - 36.00 | 2.1 - 44.44 | 41.2 - 83.15 | 14.3 - 87.55 |
## [938. Range Sum of BST][938]
**TODO: Improve Rust, don't know Ref/RefCell good enough
to readjust root correctly. I've added a minimal
Tree impl to work with in playground.**
Do an inorder traversal and sum the items. We can
cut execution time considerably by adjusting the root
before we begin the traversal.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 72 - 99.00 | 12 - 100.00 | 204 - 98.44 |184 - 99.93|
| Mem Usage (MB-%)| 42.8 - 20.00 | 4.3 - 100.00 | 67.7 - 11.10 |22.3 - 99.95|
## [942. DI String Match][942]
Initialize counters, i to zero and j to the length of the string.
Iterate through characters of string and add i if character is
'I' and j if char is 'D'. Increase and decrease the counters
respectively afterwards.
Append either i or j at the end (they should be equal) to
complete the sequence.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 32 - 98.51 | 4 - 71.43 | 100 - 65.91 | 56 - 94.27|
| Mem Usage (MB-%)| 11.6 - 34.33 | 2.2 - 28.57 | 43.1 - 21.59 | 14.9 - 83.63|
## [944. Delete Columns to Make Sorted.][944]
I cannot see the best solution here. I'm definitely sure
mine isn't the one.
| Stats/Lang | C | Rust | JS | Py |
|:-----------:|:--:|:-----:|:---:|:--:|
| Runtime (ms-%)| 16 - 90.91 | 8 - 100.00 | 88 - 82.50 | 112 - 81.53 |
| Mem Usage (MB-%)| 8.3 - 40.91 | 2.3 - 100.00 | 42.5 - 76.67 | 14.4 - 84.557|
## [961. N repeated elements in size 2N Array][961]
Two ways to go about this:
1. Build a set with 'seen' values. Break the moment we find a value we have already seen. Rust and Python use this.
2. Iterate through the array and check triplets. Since we know
that N-1 of the elements are the same, we're bound to bump into a triplet with two elements being equal. Edge case is 2N = 4, were the elements are in the