Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
▶
Steps
setup
Calculate net gas at each station
Compute net gas array where each element is gas[i] - cost[i]. This shows how much gas is gained or lost at each station.
💡 Net gas array simplifies the problem by focusing on surplus or deficit at each station.
Line:net = [gas[i] - cost[i] for i in range(n)]
💡 Net gas array reveals which stations add or consume gas, critical for checking circuit feasibility.
setup
Check total net gas sum
Sum all net gas values to verify if completing the circuit is possible at all.
💡 If total net gas is negative, no start station can complete the circuit.
Line:if sum(net) < 0:
return -1
💡 Total net gas sum >= 0 means a solution may exist.
setup
Initialize prefix sums array
Create prefix sums array of length 2*n+1 initialized with zeros to simulate circular traversal.
💡 Prefix sums allow quick calculation of net gas over any window.
Line:prefix = [0] * (2 * n + 1)
💡 Prefix sums prepare for efficient window sum queries.
fill_cells
Build prefix sums for circular net array (i=0)
Calculate prefix[1] = prefix[0] + net[0 % n], adding net at station 0.
💡 Each prefix sum accumulates net gas to enable quick window sum checks.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums grow by adding net gas values in circular order.
fill_cells
Build prefix sums for circular net array (i=1)
Calculate prefix[2] = prefix[1] + net[1 % n], adding net at station 1.
💡 Continuing prefix sums to cover twice the array length for circular wrap.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums reflect cumulative net gas over extended circular route.
fill_cells
Build prefix sums for circular net array (i=2)
Calculate prefix[3] = prefix[2] + net[2 % n], adding net at station 2.
💡 Prefix sums continue to accumulate net gas values circularly.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums enable O(1) window sum queries for any segment.
fill_cells
Build prefix sums for circular net array (i=3)
Calculate prefix[4] = prefix[3] + net[3 % n], adding net at station 3.
💡 Adding positive net gas at station 3 increases prefix sums.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Positive net gas stations increase cumulative sums, critical for feasibility.
fill_cells
Build prefix sums for circular net array (i=4)
Calculate prefix[5] = prefix[4] + net[4 % n], adding net at station 4.
💡 Completing one full cycle of prefix sums for circular array.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums now cover one full cycle of net gas values.
fill_cells
Build prefix sums for circular net array (i=5)
Calculate prefix[6] = prefix[5] + net[5 % n], adding net at station 0 again for circular wrap.
💡 Extending prefix sums to twice the array length to simulate circularity.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums allow checking any window of length n in O(1).
fill_cells
Build prefix sums for circular net array (i=6)
Calculate prefix[7] = prefix[6] + net[6 % n], adding net at station 1 again.
💡 Continuing to fill prefix sums for full circular coverage.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums now fully represent two cycles of net gas.
fill_cells
Build prefix sums for circular net array (i=7)
Calculate prefix[8] = prefix[7] + net[7 % n], adding net at station 2 again.
💡 Filling prefix sums to cover all 2*n elements.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums allow quick sum checks for any window of length n.
fill_cells
Build prefix sums for circular net array (i=8)
Calculate prefix[9] = prefix[8] + net[8 % n], adding net at station 3 again.
💡 Completing prefix sums for the circular array twice over.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums now fully represent two cycles of net gas values.
fill_cells
Build prefix sums for circular net array (i=9)
Calculate prefix[10] = prefix[9] + net[9 % n], adding net at station 4 again.
💡 Final prefix sum completes the double-length prefix sums array.
Line:prefix[i+1] = prefix[i] + net[i % n]
💡 Prefix sums array is ready for sliding window sum queries.
compare
Check window sum for start index 0
Calculate prefix[0+n] - prefix[0] = prefix[5] - prefix[0] to check if sum of net gas over stations 0 to 4 is non-negative.
💡 Checking if starting at station 0 allows completing the circuit.
Line:if prefix[i+n] - prefix[i] >= 0:
return i
💡 Window sum check shows if the circuit can be completed starting at i.
compare
Check window sum for start index 1
Calculate prefix[1+n] - prefix[1] = prefix[6] - prefix[1] to check net gas sum for stations 1 to 0 (circular).
💡 Checking if starting at station 1 allows completing the circuit.
Line:if prefix[i+n] - prefix[i] >= 0:
return i
💡 Negative window sum means starting at 1 is not feasible.
compare
Check window sum for start index 2
Calculate prefix[2+n] - prefix[2] = prefix[7] - prefix[2] to check net gas sum for stations 2 to 1 (circular).
💡 Checking if starting at station 2 allows completing the circuit.
Line:if prefix[i+n] - prefix[i] >= 0:
return i
💡 Negative window sum means starting at 2 is not feasible.
compare
Check window sum for start index 3
Calculate prefix[3+n] - prefix[3] = prefix[8] - prefix[3] to check net gas sum for stations 3 to 2 (circular).
💡 Checking if starting at station 3 allows completing the circuit.
Line:if prefix[i+n] - prefix[i] >= 0:
return i
💡 Non-negative window sum means starting at 3 completes the circuit.
reconstruct
Return the valid start index
Return the start index 3 where the circuit can be completed successfully.
💡 Returning the answer completes the algorithm.
Line:return i
💡 The algorithm finds the minimal start index with non-negative net gas window.
def canCompleteCircuit(gas, cost):
n = len(gas) # STEP 1
net = [gas[i] - cost[i] for i in range(n)] # STEP 1
if sum(net) < 0: # STEP 2
return -1
prefix = [0] * (2 * n + 1) # STEP 3
for i in range(2 * n): # STEP 4-13
prefix[i+1] = prefix[i] + net[i % n]
for i in range(n): # STEP 14-17
if prefix[i+n] - prefix[i] >= 0:
return i # STEP 18
return -1
📊
Gas Station (Circular) - Watch the Algorithm Execute, Step by Step
Watching each step reveals how the greedy approach efficiently checks feasibility without simulating the entire trip repeatedly.
Step 1/18
·Active fill★Answer cell
record
-2
0
-2
1
-2
2
3
3
3
4
compare
-2
0
-2
1
-2
2
3
3
3
4
Result: 0
record
0
0
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0
9
0
10
record
i
0
0
-2
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0
9
0
10
record
0
0
i
-2
1
-4
2
0
3
0
4
0
5
0
6
0
7
0
8
0
9
0
10
record
0
0
-2
1
i
-4
2
-6
3
0
4
0
5
0
6
0
7
0
8
0
9
0
10
record
0
0
-2
1
-4
2
i
-6
3
-3
4
0
5
0
6
0
7
0
8
0
9
0
10
record
0
0
-2
1
-4
2
-6
3
i
-3
4
0
5
0
6
0
7
0
8
0
9
0
10
record
0
0
-2
1
-4
2
-6
3
-3
4
i
0
5
-2
6
0
7
0
8
0
9
0
10
record
0
0
-2
1
-4
2
-6
3
-3
4
0
5
i
-2
6
-4
7
0
8
0
9
0
10
record
0
0
-2
1
-4
2
-6
3
-3
4
0
5
-2
6
i
-4
7
-6
8
0
9
0
10
record
0
0
-2
1
-4
2
-6
3
-3
4
0
5
-2
6
-4
7
i
-6
8
-3
9
0
10
record
0
0
-2
1
-4
2
-6
3
-3
4
0
5
-2
6
-4
7
-6
8
i
-3
9
0
10
compare
i
0
0
-2
1
-4
2
-6
3
-3
4
0
5
-2
6
-4
7
-6
8
-3
9
0
10
compare
0
0
i
-2
1
-4
2
-6
3
-3
4
0
5
-2
6
-4
7
-6
8
-3
9
0
10
compare
0
0
-2
1
i
-4
2
-6
3
-3
4
0
5
-2
6
-4
7
-6
8
-3
9
0
10
compare
0
0
-2
1
-4
2
i
-6
3
-3
4
0
5
-2
6
-4
7
-6
8
-3
9
0
10
Result: 3
record
0
0
-2
1
-4
2
start
-6
3
-3
4
0
5
-2
6
-4
7
-6
8
-3
9
0
10
Result: 3
Key Takeaways
✓ The net gas array transforms the problem into finding a non-negative sum subarray in a circular array.
This insight is hard to see from code alone because it abstracts the problem into a simpler numeric form.
✓ Prefix sums allow O(1) queries for sums over any window, enabling efficient feasibility checks.
Visualizing prefix sums clarifies why the algorithm avoids repeated summations.
✓ Checking each start index with prefix sums reveals exactly where the circuit can be completed.
Seeing each comparison step shows why some start points fail and one succeeds.
Practice
(1/5)
1. You have a list of children each with a greed factor and a list of cookies each with a size. You want to assign cookies to children so that each child gets at most one cookie and the cookie size is at least the child's greed factor. Which algorithmic approach guarantees the maximum number of content children?
easy
A. Greedy algorithm by sorting greed factors and cookie sizes, then assigning smallest sufficient cookie to each child
B. Dynamic Programming to try all possible assignments and pick the best
C. Brute force nested loops checking every cookie for every child without sorting
D. Divide and Conquer by splitting children and cookies and merging results
Solution
Step 1: Understand problem constraints
Each child can get at most one cookie, and the cookie must satisfy the child's greed factor.
Step 2: Identify optimal approach
Sorting both greed and cookie arrays allows a greedy assignment from smallest greed to smallest sufficient cookie, ensuring maximum matches.
Final Answer:
Option A -> Option A
Quick Check:
Greedy sorting approach is classic for assignment problems [OK]
Hint: Sort both arrays and assign greedily [OK]
Common Mistakes:
Thinking brute force is needed for optimality
Assuming DP is required
Ignoring sorting leads to suboptimal matches
2. You have a list of tasks represented by characters, each task takes 1 unit of time to execute. The CPU must wait for at least n units of time before executing the same task again. Which approach guarantees the minimum total time to finish all tasks?
easy
A. Dynamic Programming that tries all permutations of task orders to find the minimal schedule
B. Greedy algorithm using a max-heap to always schedule the most frequent available task next
C. Simple round-robin scheduling without considering cooldown intervals
D. Sorting tasks by frequency and inserting idle slots greedily without priority queue
Solution
Step 1: Understand the cooldown constraint
The CPU must wait n units before repeating the same task, so scheduling must consider task frequencies and cooldowns.
Step 2: Why max-heap greedy works best
Using a max-heap prioritizes tasks with the highest remaining frequency, ensuring minimal idle time by always picking the most urgent task available.
Final Answer:
Option B -> Option B
Quick Check:
Max-heap approach matches known optimal solution [OK]
Hint: Max-heap greedily schedules highest frequency tasks first [OK]
Common Mistakes:
Assuming DP or brute force is needed
Ignoring cooldown leads to incorrect minimal time
Greedy without priority queue misses optimal order
3. Identify the bug in the following code snippet for Two City Scheduling:
def twoCitySchedCost(costs):
costs.sort(key=lambda x: abs(x[0] - x[1]))
n = len(costs) // 2
total = 0
for i, cost in enumerate(costs):
if i < n:
total += cost[0]
else:
total += cost[1]
return total
medium
A. Sorting by absolute difference instead of signed difference
B. Incorrect calculation of n as half the length
C. Adding cost[1] for the first half instead of cost[0]
D. Using enumerate instead of a simple for loop
Solution
Step 1: Analyze sorting key
The code sorts by absolute difference abs(cost[0] - cost[1]) instead of signed difference cost[0] - cost[1].
Step 2: Effect of wrong sorting
Sorting by absolute difference loses the direction of cost preference, causing suboptimal assignments and higher total cost.
Final Answer:
Option A -> Option A
Quick Check:
Signed difference sorting is required for correct greedy assignment [OK]
Hint: Sort by signed difference, not absolute [OK]
Common Mistakes:
Sorting by absolute difference
Miscounting half the people
Swapping city costs in assignment
4. Suppose the problem changes: you can reuse indices multiple times (cycles allowed). Which modification to the BFS approach ensures correct minimum jumps without infinite loops?
hard
A. Remove the visited set to allow revisiting indices for better paths.
B. Keep the visited set but reset it after each BFS level to allow revisits in next level.
C. Keep the visited set as is to prevent revisiting and infinite loops.
D. Use a distance array to track minimum jumps to each index and update it if a shorter path is found.
Solution
Step 1: Understand cycles and revisits
Allowing reuse means indices can be revisited, so visited set alone blocks better paths.
Step 2: Use distance array for shortest paths
Tracking minimum jumps per index and updating when a shorter path is found prevents infinite loops and finds optimal jumps.
Distance array with updates handles cycles correctly [OK]
Hint: Distance array needed when revisits allowed [OK]
Common Mistakes:
Removing visited set causing infinite loops
Resetting visited incorrectly
Assuming original BFS works unchanged
5. Suppose the wiggle subsequence problem is modified so that elements can be reused multiple times in the subsequence (i.e., repeated picks allowed). Which of the following statements about adapting the optimal greedy algorithm is correct?
hard
A. A modified greedy approach can work by allowing zero differences and counting repeated elements
B. The original greedy algorithm works without changes because reuse does not affect difference signs
C. Reuse breaks the problem definition, so no efficient algorithm exists
D. The algorithm must be changed to a dynamic programming approach to handle reuse correctly
Solution
Step 1: Understand reuse impact
Allowing reuse means subsequence elements can repeat, changing the problem fundamentally and invalidating the original greedy assumptions.
Step 2: Identify correct adaptation
Greedy approach relies on strictly alternating differences without reuse; to handle reuse, a dynamic programming approach that tracks states and counts is needed.
Final Answer:
Option D -> Option D
Quick Check:
Reuse requires more complex state tracking than greedy allows [OK]