Skip to content

Commit e46cc42

Browse files
authored
feat: add gas_station (#50)
1 parent 68521e3 commit e46cc42

File tree

10 files changed

+269
-43
lines changed

10 files changed

+269
-43
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VERSION = 3.13
2-
PROBLEM ?= house_robber
2+
PROBLEM ?= gas_station
33
FORCE ?= 0
44
COMMA := ,
55

leetcode/gas_station/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Gas Station
2+
3+
**Difficulty:** Medium
4+
**Topics:** Array, Greedy
5+
**Tags:** grind
6+
7+
**LeetCode:** [Problem 134](https://leetcode.com/problems/gas-station/description/)
8+
9+
## Problem Description
10+
11+
There are `n` gas stations along a circular route, where the amount of gas at the `ith` station is `gas[i]`.
12+
13+
You have a car with an unlimited gas tank and it costs `cost[i]` of gas to travel from the `ith` station to its next `(i + 1)th` station. You begin the journey with an empty tank at one of the gas stations.
14+
15+
Given two integer arrays `gas` and `cost`, return _the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return_ `-1`. If there exists a solution, it is **guaranteed** to be **unique**.
16+
17+
## Examples
18+
19+
### Example 1:
20+
21+
```
22+
Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
23+
Output: 3
24+
Explanation:
25+
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
26+
Travel to station 4. Your tank = 4 - 1 + 5 = 8
27+
Travel to station 0. Your tank = 8 - 2 + 1 = 7
28+
Travel to station 1. Your tank = 7 - 3 + 2 = 6
29+
Travel to station 2. Your tank = 6 - 4 + 3 = 5
30+
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
31+
Therefore, return 3 as the starting index.
32+
```
33+
34+
### Example 2:
35+
36+
```
37+
Input: gas = [2,3,4], cost = [3,4,3]
38+
Output: -1
39+
Explanation:
40+
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
41+
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
42+
Travel to station 0. Your tank = 4 - 3 + 2 = 3
43+
Travel to station 1. Your tank = 3 - 3 + 3 = 3
44+
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
45+
Therefore, you can't travel around the circuit once no matter where you start.
46+
```
47+
48+
## Constraints
49+
50+
- `n == gas.length == cost.length`
51+
- `1 <= n <= 10^5`
52+
- `0 <= gas[i], cost[i] <= 10^4`
53+
- The input is generated such that the answer is unique.

leetcode/gas_station/__init__.py

Whitespace-only changes.

leetcode/gas_station/helpers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def run_can_complete_circuit(solution_class: type, gas: list[int], cost: list[int]):
2+
implementation = solution_class()
3+
return implementation.can_complete_circuit(gas, cost)
4+
5+
6+
def assert_can_complete_circuit(result: int, expected: int) -> bool:
7+
assert result == expected
8+
return True

leetcode/gas_station/playground.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# text_representation:
5+
# extension: .py
6+
# format_name: percent
7+
# format_version: '1.3'
8+
# jupytext_version: 1.17.3
9+
# kernelspec:
10+
# display_name: leetcode-py-py3.13
11+
# language: python
12+
# name: python3
13+
# ---
14+
15+
# %%
16+
from helpers import assert_can_complete_circuit, run_can_complete_circuit
17+
from solution import Solution
18+
19+
# %%
20+
# Example test case
21+
gas = [1, 2, 3, 4, 5]
22+
cost = [3, 4, 5, 1, 2]
23+
expected = 3
24+
25+
# %%
26+
result = run_can_complete_circuit(Solution, gas, cost)
27+
result
28+
29+
# %%
30+
assert_can_complete_circuit(result, expected)

leetcode/gas_station/solution.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
class Solution:
2+
"""
3+
Gas Station Circuit - Greedy Approach
4+
5+
Visual Example: gas=[1,2,3,4,5], cost=[3,4,5,1,2]
6+
7+
Station: 0 1 2 3 4
8+
┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
9+
Gas: │1│ │2│ │3│ │4│ │5│
10+
└─┘ └─┘ └─┘ └─┘ └─┘
11+
Cost: 3 4 5 1 2
12+
↓ ↓ ↓ ↓ ↓
13+
Net: -2 -2 -2 +3 +3
14+
15+
Algorithm trace:
16+
i=0: tank=0+(-2)=-2 < 0 → reset tank=0, start=1
17+
i=1: tank=0+(-2)=-2 < 0 → reset tank=0, start=2
18+
i=2: tank=0+(-2)=-2 < 0 → reset tank=0, start=3
19+
i=3: tank=0+(+3)=+3 ≥ 0 → continue
20+
i=4: tank=3+(+3)=+6 ≥ 0 → return start=3
21+
22+
Key insight: If total_gas ≥ total_cost, greedy start position works!
23+
"""
24+
25+
# Time: O(n)
26+
# Space: O(1)
27+
def can_complete_circuit(self, gas: list[int], cost: list[int]) -> int:
28+
if sum(gas) < sum(cost):
29+
return -1
30+
31+
tank = start = 0
32+
for i in range(len(gas)):
33+
tank += gas[i] - cost[i]
34+
if tank < 0:
35+
tank = 0
36+
start = i + 1
37+
return start
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import pytest
2+
3+
from leetcode_py import logged_test
4+
5+
from .helpers import assert_can_complete_circuit, run_can_complete_circuit
6+
from .solution import Solution
7+
8+
9+
class TestGasStation:
10+
def setup_method(self):
11+
self.solution = Solution()
12+
13+
@logged_test
14+
@pytest.mark.parametrize(
15+
"gas, cost, expected",
16+
[
17+
([1, 2, 3, 4, 5], [3, 4, 5, 1, 2], 3),
18+
([2, 3, 4], [3, 4, 3], -1),
19+
([1, 2], [2, 1], 1),
20+
([5], [4], 0),
21+
([2], [2], 0),
22+
([1, 2, 3], [3, 3, 3], -1),
23+
([3, 1, 1], [1, 2, 2], 0),
24+
([5, 1, 2, 3, 4], [4, 4, 1, 5, 1], 4),
25+
([1, 2, 3, 4, 5, 5, 70], [2, 3, 4, 3, 9, 6, 2], 6),
26+
([4, 5, 2, 6, 5, 3], [3, 2, 7, 3, 2, 9], -1),
27+
([6, 1, 4, 3, 5], [3, 8, 2, 4, 2], 2),
28+
([2, 3, 4, 5], [3, 4, 5, 6], -1),
29+
],
30+
)
31+
def test_can_complete_circuit(self, gas: list[int], cost: list[int], expected: int):
32+
result = run_can_complete_circuit(Solution, gas, cost)
33+
assert_can_complete_circuit(result, expected)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"problem_name": "gas_station",
3+
"solution_class_name": "Solution",
4+
"problem_number": "134",
5+
"problem_title": "Gas Station",
6+
"difficulty": "Medium",
7+
"topics": "Array, Greedy",
8+
"readme_description": "There are `n` gas stations along a circular route, where the amount of gas at the `ith` station is `gas[i]`.\n\nYou have a car with an unlimited gas tank and it costs `cost[i]` of gas to travel from the `ith` station to its next `(i + 1)th` station. You begin the journey with an empty tank at one of the gas stations.\n\nGiven two integer arrays `gas` and `cost`, return *the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return* `-1`. If there exists a solution, it is **guaranteed** to be **unique**.",
9+
"_readme_examples": {
10+
"list": [
11+
{
12+
"content": "```\nInput: gas = [1,2,3,4,5], cost = [3,4,5,1,2]\nOutput: 3\nExplanation:\nStart at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4\nTravel to station 4. Your tank = 4 - 1 + 5 = 8\nTravel to station 0. Your tank = 8 - 2 + 1 = 7\nTravel to station 1. Your tank = 7 - 3 + 2 = 6\nTravel to station 2. Your tank = 6 - 4 + 3 = 5\nTravel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.\nTherefore, return 3 as the starting index.\n```"
13+
},
14+
{
15+
"content": "```\nInput: gas = [2,3,4], cost = [3,4,3]\nOutput: -1\nExplanation:\nYou can't start at station 0 or 1, as there is not enough gas to travel to the next station.\nLet's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4\nTravel to station 0. Your tank = 4 - 3 + 2 = 3\nTravel to station 1. Your tank = 3 - 3 + 3 = 3\nYou cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.\nTherefore, you can't travel around the circuit once no matter where you start.\n```"
16+
}
17+
]
18+
},
19+
"readme_constraints": "- `n == gas.length == cost.length`\n- `1 <= n <= 10^5`\n- `0 <= gas[i], cost[i] <= 10^4`\n- The input is generated such that the answer is unique.",
20+
"helpers_imports": "",
21+
"helpers_content": "",
22+
"helpers_run_name": "can_complete_circuit",
23+
"helpers_run_signature": "(solution_class: type, gas: list[int], cost: list[int])",
24+
"helpers_run_body": " implementation = solution_class()\n return implementation.can_complete_circuit(gas, cost)",
25+
"helpers_assert_name": "can_complete_circuit",
26+
"helpers_assert_signature": "(result: int, expected: int) -> bool",
27+
"helpers_assert_body": " assert result == expected\n return True",
28+
"solution_imports": "",
29+
"solution_contents": "",
30+
"solution_class_content": "",
31+
"test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_can_complete_circuit, run_can_complete_circuit\nfrom .solution import Solution",
32+
"test_content": "",
33+
"test_class_name": "GasStation",
34+
"test_class_content": " def setup_method(self):\n self.solution = Solution()",
35+
"_solution_methods": {
36+
"list": [
37+
{
38+
"name": "can_complete_circuit",
39+
"signature": "(self, gas: list[int], cost: list[int]) -> int",
40+
"body": " # TODO: Implement can_complete_circuit\n return -1"
41+
}
42+
]
43+
},
44+
"_test_helper_methods": {
45+
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
46+
},
47+
"_test_methods": {
48+
"list": [
49+
{
50+
"name": "test_can_complete_circuit",
51+
"signature": "(self, gas: list[int], cost: list[int], expected: int)",
52+
"parametrize": "gas, cost, expected",
53+
"test_cases": "[([1,2,3,4,5], [3,4,5,1,2], 3), ([2,3,4], [3,4,3], -1), ([1,2], [2,1], 1), ([5], [4], 0), ([2], [2], 0), ([1,2,3], [3,3,3], -1), ([3,1,1], [1,2,2], 0), ([5,1,2,3,4], [4,4,1,5,1], 4), ([1,2,3,4,5,5,70], [2,3,4,3,9,6,2], 6), ([4,5,2,6,5,3], [3,2,7,3,2,9], -1), ([6,1,4,3,5], [3,8,2,4,2], 2), ([2,3,4,5], [3,4,5,6], -1)]",
54+
"body": " result = run_can_complete_circuit(Solution, gas, cost)\n assert_can_complete_circuit(result, expected)"
55+
}
56+
]
57+
},
58+
"playground_imports": "from helpers import run_can_complete_circuit, assert_can_complete_circuit\nfrom solution import Solution",
59+
"playground_setup": "# Example test case\ngas = [1,2,3,4,5]\ncost = [3,4,5,1,2]\nexpected = 3",
60+
"playground_run": "result = run_can_complete_circuit(Solution, gas, cost)\nresult",
61+
"playground_assert": "assert_can_complete_circuit(result, expected)"
62+
}

leetcode_py/cli/resources/leetcode/json/tags.json5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"zero_one_matrix",
7979
],
8080

81-
grind: [{ tag: "grind-75" }, "daily_temperatures", "house_robber"],
81+
grind: [{ tag: "grind-75" }, "daily_temperatures", "gas_station", "house_robber"],
8282

8383
// Test tag for development and testing
8484
test: ["binary_search", "two_sum", "valid_palindrome"],

0 commit comments

Comments
 (0)