Skip to content
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 Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYTHON_VERSION = 3.13
PROBLEM ?= house_robber
PROBLEM ?= gas_station
FORCE ?= 0
COMMA := ,

Expand Down
53 changes: 53 additions & 0 deletions leetcode/gas_station/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Gas Station

**Difficulty:** Medium
**Topics:** Array, Greedy
**Tags:** grind

**LeetCode:** [Problem 134](https://leetcode.com/problems/gas-station/description/)

## Problem Description

There are `n` gas stations along a circular route, where the amount of gas at the `ith` station is `gas[i]`.

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.

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**.

## Examples

### Example 1:

```
Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
Output: 3
Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.
```

### Example 2:

```
Input: gas = [2,3,4], cost = [3,4,3]
Output: -1
Explanation:
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can't travel around the circuit once no matter where you start.
```

## Constraints

- `n == gas.length == cost.length`
- `1 <= n <= 10^5`
- `0 <= gas[i], cost[i] <= 10^4`
- The input is generated such that the answer is unique.
Empty file.
8 changes: 8 additions & 0 deletions leetcode/gas_station/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def run_can_complete_circuit(solution_class: type, gas: list[int], cost: list[int]):
implementation = solution_class()
return implementation.can_complete_circuit(gas, cost)


def assert_can_complete_circuit(result: int, expected: int) -> bool:
assert result == expected
return True
30 changes: 30 additions & 0 deletions leetcode/gas_station/playground.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.17.3
# kernelspec:
# display_name: leetcode-py-py3.13
# language: python
# name: python3
# ---

# %%
from helpers import assert_can_complete_circuit, run_can_complete_circuit
from solution import Solution

# %%
# Example test case
gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
expected = 3

# %%
result = run_can_complete_circuit(Solution, gas, cost)
result

# %%
assert_can_complete_circuit(result, expected)
37 changes: 37 additions & 0 deletions leetcode/gas_station/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class Solution:
"""
Gas Station Circuit - Greedy Approach

Visual Example: gas=[1,2,3,4,5], cost=[3,4,5,1,2]

Station: 0 1 2 3 4
┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
Gas: │1│ │2│ │3│ │4│ │5│
└─┘ └─┘ └─┘ └─┘ └─┘
Cost: 3 4 5 1 2
↓ ↓ ↓ ↓ ↓
Net: -2 -2 -2 +3 +3

Algorithm trace:
i=0: tank=0+(-2)=-2 < 0 → reset tank=0, start=1
i=1: tank=0+(-2)=-2 < 0 → reset tank=0, start=2
i=2: tank=0+(-2)=-2 < 0 → reset tank=0, start=3
i=3: tank=0+(+3)=+3 ≥ 0 → continue
i=4: tank=3+(+3)=+6 ≥ 0 → return start=3

Key insight: If total_gas ≥ total_cost, greedy start position works!
"""

# Time: O(n)
# Space: O(1)
def can_complete_circuit(self, gas: list[int], cost: list[int]) -> int:
if sum(gas) < sum(cost):
return -1

tank = start = 0
for i in range(len(gas)):
tank += gas[i] - cost[i]
if tank < 0:
tank = 0
start = i + 1
return start
33 changes: 33 additions & 0 deletions leetcode/gas_station/test_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pytest

from leetcode_py import logged_test

from .helpers import assert_can_complete_circuit, run_can_complete_circuit
from .solution import Solution


class TestGasStation:
def setup_method(self):
self.solution = Solution()

@logged_test
@pytest.mark.parametrize(
"gas, cost, expected",
[
([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),
],
)
def test_can_complete_circuit(self, gas: list[int], cost: list[int], expected: int):
result = run_can_complete_circuit(Solution, gas, cost)
assert_can_complete_circuit(result, expected)
62 changes: 62 additions & 0 deletions leetcode_py/cli/resources/leetcode/json/problems/gas_station.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"problem_name": "gas_station",
"solution_class_name": "Solution",
"problem_number": "134",
"problem_title": "Gas Station",
"difficulty": "Medium",
"topics": "Array, Greedy",
"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**.",
"_readme_examples": {
"list": [
{
"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```"
},
{
"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```"
}
]
},
"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.",
"helpers_imports": "",
"helpers_content": "",
"helpers_run_name": "can_complete_circuit",
"helpers_run_signature": "(solution_class: type, gas: list[int], cost: list[int])",
"helpers_run_body": " implementation = solution_class()\n return implementation.can_complete_circuit(gas, cost)",
"helpers_assert_name": "can_complete_circuit",
"helpers_assert_signature": "(result: int, expected: int) -> bool",
"helpers_assert_body": " assert result == expected\n return True",
"solution_imports": "",
"solution_contents": "",
"solution_class_content": "",
"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",
"test_content": "",
"test_class_name": "GasStation",
"test_class_content": " def setup_method(self):\n self.solution = Solution()",
"_solution_methods": {
"list": [
{
"name": "can_complete_circuit",
"signature": "(self, gas: list[int], cost: list[int]) -> int",
"body": " # TODO: Implement can_complete_circuit\n return -1"
}
]
},
"_test_helper_methods": {
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
},
"_test_methods": {
"list": [
{
"name": "test_can_complete_circuit",
"signature": "(self, gas: list[int], cost: list[int], expected: int)",
"parametrize": "gas, cost, expected",
"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)]",
"body": " result = run_can_complete_circuit(Solution, gas, cost)\n assert_can_complete_circuit(result, expected)"
}
]
},
"playground_imports": "from helpers import run_can_complete_circuit, assert_can_complete_circuit\nfrom solution import Solution",
"playground_setup": "# Example test case\ngas = [1,2,3,4,5]\ncost = [3,4,5,1,2]\nexpected = 3",
"playground_run": "result = run_can_complete_circuit(Solution, gas, cost)\nresult",
"playground_assert": "assert_can_complete_circuit(result, expected)"
}
2 changes: 1 addition & 1 deletion leetcode_py/cli/resources/leetcode/json/tags.json5
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"zero_one_matrix",
],

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

// Test tag for development and testing
test: ["binary_search", "two_sum", "valid_palindrome"],
Expand Down
Loading