Problem described here.
Breakdown
- We have an inter
An algorithm is greedy if it tries to find the best local solution at each step with the hope that the best global solution will be found in the process. And sometimes this works!
Let’s say you were at Comic-con and wanted to ensure that you’re day was as full as possible. After all, you want to maximize your experience.
And these are your options:
Seminar | Start | End |
---|---|---|
Artist meet | 9 AM | 10 AM |
Interview with Stan Lee | 9:30 AM | 10:30 AM |
V for Vendetta cast | 10 AM | 11 AM |
Ironman preview | 10:30 AM | 11:30 AM |
Spiderman preview | 11 AM | 12 PM |
This looks something like this:
We need to look at a few more examples to come up with a strategy of picking the right seminars. Let’s have a look at a few generic examples of events below.
But let’s look closer at why we pick these and how we would formalize it.
If we just picked the shortest events, that may not always be optimal. Picking the ones that start the earliest is
also not enough.
A good example is the Task Scheduler.
So the input is a string like this:1
"245300"
And we need to delete 2 digits so that we get a minimum value.
Well, my first thought was something like this:1
2
3
4
5del 2 & 4 --> 5300
or del 2 & 5 --> 4300
or del 2 & 3 --> 4500
...etc...
or del 0 and 0 --> 2453
But boy does that get tedious fast 😧. Not to mention, that you basically have O(n^2)
time which is not acceptable.
Ok so let’s first try some examples to understand the basic characteristics of a number.
Let’s look at how a base 10 number is composed:1
352 = 3 * 100 + 5 * 10 + 2
Which means that intuitively, each digit gets more weight as we move left. Each move left is an order of magnitude.
Armed with this understanding we can try to visualize the number as follows:
If we need to remove one digit and get the smallest value, can you see which one we would remove?
1 | Due to the nature of the problem, if we were to remove the digit `5`, we would end up |
Let’s see another example. What if the input was 1432219
and we want to remove two digits?
Ok, let’s think of a sub-problem: what if we want to remove one digit?
1 | 432219 |
Well the smallest one there is 132219
Let’s look at this closer. Look at just the first two digits of that. What’s the smallest one? 13?
Interesting!
So that tells us that the first two digits really determine the result here.
But why?
Recall the diagram of the number we saw earlier? The left-most digit has the most weight and digits slide
left to right when a removal is performed. So, having understood that, we see that removing anything to the right of 4 will not take enough weight off. And removing 4 will remove the most weight since the 1 will slide into its place.
Based on the idea above, we can solve the problem as a series of subproblems: remove one digit at a time until k
digits
are removed. For each subproblem, we need to find a ‘peak’ and then remove that number.
1 | /** |
Note that we need to explicitly do pop()
if we never found any peaks, such as in 33333
or 1234
!
In this case, we should just delete k
digits from the end (and not the beginning , recall that 65432
has a peak).
Also we need to strip out any leading zeroes. And for the case when we have all zeroes, such as 0000
, we should explicitly return a 0
!
Another thing to note is that in order to strip out leading zeroes we could have done String(Number(res.join('')))
.
However, when the string is very long Number()
could result in Infinity
. So we do it manually instead.
This works, but the problem is that we are iterating the array for each sub-problem. So our runtime is O(k*n)
. We can
do better.
Is it possible to somehow track the digits we have already visited?
Yes! We can use a list.
1 | class Solution { |
The reason why we cannot do something like the following is that modifying the string while iterating it
is incorrect:1
2
3
4for (auto iter = res.begin(); iter != res.end(); iter++) {
if (*iter == '0') res.erase(iter);
else break;
}
Obligatory hello world post.
Stay tuned for more!