Greedy · 13 of 35
Check if it is possible to survive on Island
Stuck on an island where the only shop shuts on Sundays, find the fewest shopping days that keep you fed, or say it cannot be done.
- Simple way
- time O(S)
room O(1) - Clever way
- time O(1)
room O(1)
The problem, simply
You are on an island for S days. Today is Monday. There is one shop. It is open every day except Sunday, and on each visit it sells you at most N units of food. You must eat M units every day, and you can store as much food as you like.
Give back the smallest number of days you need to go shopping to survive all S days, or -1 if you cannot survive. You may shop and then eat on the same day.
A story to remember it
Picture it
S = 9, N = 9, M = 7. Each box is the food left at the end of that day if you shop whenever you still need food. Sunday is closed.
- done
- ignored
Examples
A normal case
- In
S = 9, N = 9, M = 7- Out
7
You need 9 x 7 = 63 units. Each visit gives at most 9, so 7 visits. Saturday's pile of 12 covers Sunday.
Plenty of food
- In
S = 10, N = 16, M = 2- Out
2
You need 20 units. Two visits of 16 cover it, and you never run out.
Shop too small
- In
S = 10, N = 20, M = 30- Out
-1
You eat 30 on day 1, but the shop sells only 20.
Starving on the first Sunday
- In
S = 13, N = 13, M = 12- Out
-1
There are enough open days in total, but by Sunday you have bought 6 x 13 = 78 and need 7 x 12 = 84.
Short stay
- In
S = 6, N = 9, M = 8- Out
6
You leave before Sunday, so the weekly check does not matter. 48 units need 6 visits.
Way 1: the simple way
Live through every day.
- Keep
foodin the pantry andboughtso far. - On each day that is not a Sunday, if you have not yet bought
S * Min total, buyNand count one shopping day. - Eat
M. Iffooddrops below 0, return -1. - After the last day, return the count.
Buying as early as possible is never worse, because stored food does not spoil.
class Solution {
public int minimumDays(int S, int N, int M) {
long need = (long) S * M;
long food = 0, bought = 0;
int days = 0;
for (int d = 1; d <= S; d++) {
boolean sunday = d % 7 == 0; // day 1 is Monday
if (!sunday && bought < need) {
food += N;
bought += N;
days++;
}
food -= M; // eat
if (food < 0) return -1;
}
return days;
}
}How long it takes: one step per day, O(S). Extra room: a few numbers, O(1).
Way 2: the clever way
Three small checks replace the whole simulation.
- If
M > N, you starve on day 1. Return -1. - If you stay at least 7 days, the first Sunday is the danger. By then you can have bought at most
6 * Nand you have eaten7 * M. If6 * N < 7 * M, return -1. If it passes, every later week works the same way, so you never starve. - Otherwise you need
S * Munits, and each visit gives at mostN. The answer isS * M / Nrounded up.
Three checks instead of living every day
01 / 06
Example: S = 9 days, the shop sells N = 9, you eat M = 7. Check 1: is M more than N? 7 is not more than 9, so day 1 is safe.
- N
- 9
- M
- 7
- checking
- done
- rejected
- ignored
class Solution {
public int minimumDays(int S, int N, int M) {
if (M > N) return -1; // starve on day 1
if (S >= 7 && 6L * N < 7L * M) return -1; // starve on the first Sunday
long need = (long) S * M;
return (int) ((need + N - 1) / N); // visits, rounded up
}
}How long it takes: a few multiplications, O(1). Extra room: O(1).
Watch out for
- Day 1 is Monday, so Sundays are days 7, 14, 21, and so on.
S * Mcan be large. Uselongbefore dividing.- Round up:
(need + N - 1) / N, notneed / N. - If you stay fewer than 7 days, there is no Sunday, so skip the Sunday check.
What interviewers ask next
- Why does passing the first Sunday mean every later Sunday is fine? Each full week you can buy
6 * Nand eat7 * M. If one week works, the food left over only grows, week after week. - Why is shopping early always best? Food keeps, so having it sooner never hurts. That is why the fewest visits is the rounded up division.
- What if the pantry can hold at most
Cunits? Then you cannot stock up for Sunday freely. Simulate, buyingmin(N, C - food)each open day, and the answer can change. - What if today is not Monday? Count the open days before the first Sunday and check that
open * N >= (open + 1) * M, then use the same weekly check.
Remember this
Grown-up words: the pantry is a running balance, shopping early is a greedy choice, and the weekly check is the invariant that makes the closed form answer safe.