Skip to content

chore(book/array): improve exercises #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion book/config
54 changes: 45 additions & 9 deletions book/content/part02/array.asc
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,29 @@ To sum up, the time complexity of an array is:

Many programming problems involve manipulating arrays. Here are some patterns that can help you improve your problem-solving skills.

(((Patterns, Two Pointers)))

===== Two Pointers Pattern

Usually, we use one pointer to navigate each element in an array. However, there are times when having two pointers (left/right, low/high) comes in handy. Let's do some examples.

*AR-A*) _Given a sorted `array` of integers, find two numbers that add up to a `target` and return their values._

.Function Signature
[source, javascript]
----
/**
* Find two numbers that add up target.
* @param arr - The array of integers
* @param target - The target
* @returns {number[]} - array with the values that add up to target.
*/
function twoSum(arr, target) {
// give it a try on your own ...
}
----


.Examples
[source, javascript]
----
Expand Down Expand Up @@ -335,7 +352,7 @@ We can use two pointers: one pointer starting from the left side and the other f

Depending on whether the sum is bigger or smaller than the target, we move right or left. If the sum is equal to the target, we return the current left and right pointer's values.

.Solution 1: Two Pointers
.Solution 2: Two Pointers
[source, javascript]
----
function twoSum(arr, target) {
Expand All @@ -354,12 +371,30 @@ These two pointers have a runtime of `O(n)`.

WARNING: This technique only works for sorted arrays. If the array was not sorted, you would have to sort it first or choose another approach.

===== Sliding Windows Pattern
(((Patterns, Sliding Window Pointers)))

===== Sliding Window Pattern

The sliding window pattern is similar to the two pointers. The difference is that the distance between the left and right pointer is always the same. Also, the numbers don't need to be sorted. Let's do an example!

*AR-B*) _Find the max sum of an array of integers, only taking `k` items from the right and left side sequentially._
_*Constraints*: `k` won't exceed the number of elements `n`: `1 <= k <= n`._
**Constraints**: `k` won't exceed the number of elements in the array: `1 <= k <= n`.

.Function Signature
[source, javascript]
----
/**
* Find the max sum of an array of integers,
* only taking `k` items from the right and left side.
*
* @param {number[]} arr - The array of integers
* @param {number} k - The number of elements to sum up.
* @returns {number}
*/
function maxSum(arr, k) {
// Give it a try
};
----

.Examples
[source, javascript]
Expand All @@ -370,23 +405,23 @@ maxSum([3, 10, 12, 4, 7, 2, 100, 1], 3); // 104 // (3 + 1 + 100 = 104)
maxSum([1,200,1], 1); // 6 // (1 + 2 + 3 = 6)
----

Let's take `[3, 10, 12, 4, 7, 2, 100, 1], k=3` as an example.

There are multiple ways to solve this problem. Before applying the sliding window, let's consider this other algorithm:

*Backtracking algorithm*

Let's take `[3, 10, 12, 4, 7, 2, 100, 1], k = 3` as an example.

- We have two initial choices: going left with `3` or right with `1`.
- We can take the first element from the left side `3`; from there, we can keep going left with `10` or right `1`.
- If we go right with `1` on the right side, next, we have two options from the right side `100` or `10`.
- If we go with `100`, then we compute the sum `3 + 1 + 100 = 104`.
- Repeat with other combinations and keep track of the max sum.

How many combinations can we form? 2^k, since in the worst-case k is n, then we have a runtime of `2^n`!
How many combinations can we form? `2^k`, since in the worst-case `k` is equal to `n`, then we have a runtime of `O(2^n)`!

// image::max-sum-backtracking.png[max sum with backtracking]

We can also visualize all the options as follows. If you add up the numbers from the top to bottom, you get the result for all combinations:
We can also visualize all the options as follows. If you add up the numbers from top to bottom, you get the result for all combinations:

[graphviz, max-sum-sliding-window-red, png]
....
Expand Down Expand Up @@ -438,7 +473,7 @@ graph G {
....


Notice that many elements on the middle branches (in red color) have the same numbers but in a different order, so the sums oscillate between 104 and 14. That's why this algorithm is not very optimal for this problem.
Notice that many middle branches (in red color) have the same numbers, but in a different order, so their sums oscillate between 104 and 14. That's why this algorithm is not very optimal for this problem.

*Sliding window algorithm*

Expand All @@ -450,6 +485,7 @@ image::max-sum-sliding-window.png[sliding window for arrays]

Here's the implementation:

.Solution: using sliding window pointers
[source, javascript]
----
function maxSum(arr, k) {
Expand All @@ -470,7 +506,7 @@ function maxSum(arr, k) {

The difference between the two pointers pattern and the sliding windows, it's that we move both pointers at the same time to keep the length of the window the same.

The runtime for this code is: `O(k)`. We move the window k times. Since `k <= n`, the final runtime is `O(n)`.
The runtime for this code is: `k`. As we move the window k times. Since `k <= n`, the final runtime is `O(n)`.

==== Practice Questions
(((Interview Questions, Arrays)))
Expand Down
Binary file added book/images/max-sum-sliding-window-red.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.