Talentd
FleetCode
Make and follow sheets.Sign in

Minimum Number of Food Buckets to Feed the Hamsters solution and explanation

MediumDynamic ProgrammingGreedyString5 min read48.1% acceptanceUpdated 9 Apr 2026
Leetcode 2086. Minimum Number of Food Buckets to Feed the Hamsters (greedy)LetsCode · 7:22 · 684 viewsWatch on YouTube
1 more video on this problem
  1. Leetcode 2086. Minimum Number of Food Buckets to Feed the Hamsters (greedy)LetsCode · 7:22 · 684 views
  2. Leetcode 2086 Minimum Number of Food Buckets to Feed the HamstersAlgorithmicIQ · 20:27 · 296 views

The problem

You are given a 0-indexed string hamsters where hamsters[i] is either:

  • 'H' indicating that there is a hamster at index i, or
  • '.' indicating that index i is empty.

You will add some number of food buckets at the empty indices in order to feed the hamsters. A hamster can be fed if there is at least one food bucket to its left or to its right. More formally, a hamster at index i can be fed if you place a food bucket at index i - 1 and/or at index i + 1.

Return the minimum number of food buckets you should place at empty indices to feed all the hamsters or -1 if it is impossible to feed all of them.

Example 1:

Input: hamsters = "H..H"
Output: 2
Explanation: We place two food buckets at indices 1 and 2.
It can be shown that if we place only one food bucket, one of the hamsters will not be fed.

Example 2:

Input: hamsters = ".H.H."
Output: 1
Explanation: We place one food bucket at index 2.

Example 3:

Input: hamsters = ".HHH."
Output: -1
Explanation: If we place a food bucket at every empty index as shown, the hamster at index 2 will not be able to eat.

Constraints:

  • 1 <= hamsters.length <= 105
  • hamsters[i] is either'H' or '.'.

Approach overview

Problem Overview: You receive a street represented as a string where 'H' is a hamster house and '.' is an empty spot. A food bucket placed on '.' can feed adjacent hamsters (left or right). The goal is to place the minimum number of buckets so every hamster has at least one adjacent bucket. If any hamster cannot be fed, return -1.

Approach 1: Greedy Placement (O(n) time, O(1) space)

This problem works well with a greedy strategy. Iterate through the street from left to right. When you encounter a hamster, try to place a bucket to its right first if the spot is empty. That bucket can potentially serve both the current hamster and the next one, which minimizes total buckets. If the right side is unavailable, check the left side. If neither side has an empty position, feeding this hamster is impossible and the answer is -1. The key insight: placing the bucket on the right side whenever possible maximizes sharing between neighboring hamsters.

During iteration, mark the bucket placement logically and continue scanning. Because each character is processed once and bucket placement decisions are local, the algorithm runs in linear time with constant extra memory. This is the most common interview solution because it balances correctness with simplicity.

Approach 2: Two-Pass Strategy (O(n) time, O(n) space)

A structured alternative uses two passes over the string. In the first pass, handle hamsters that must place a bucket on a specific side (for example, when only one adjacent spot is available). Record placements in an auxiliary array representing bucket positions. In the second pass, process remaining hamsters and place buckets where they can serve multiple houses efficiently. This staged decision process avoids conflicts where multiple hamsters compete for the same location.

This approach resembles techniques used in dynamic programming-style constraint handling, where earlier decisions influence later placements. While the complexity is still linear, it uses extra memory to track bucket states and is slightly more verbose than the greedy solution. The advantage is clearer separation between forced placements and optimal placements.

Recommended for interviews: The greedy approach is the expected solution. Interviewers want to see whether you recognize the local optimal rule: prioritize placing buckets to the right of each hamster to allow sharing with the next house. Discussing the two-pass strategy shows you understand constraint handling, but implementing the greedy single-pass solution demonstrates stronger problem-solving intuition and leads directly to the optimal O(n) time and O(1) space solution.

Approach 1: Greedy Approach

In this approach, we'll iterate through the string and place buckets at appropriate indices to minimize the total number of buckets while ensuring all hamsters are fed. We'll attempt to place a bucket to the hamster's right first, as it can potentially serve future hamsters on the right, promoting efficiency.

def min_buckets(hamsters: str) -> int:
    buckets = 0
    i = 0
    n = len(hamsters)

    while i < n:
        if hamsters[i] == 'H':
            if i + 1 < n and hamsters[i + 1] == '.':
                buckets += 1
                i += 2
            elif i > 0 and hamsters[i - 1] == '.':
                buckets += 1
                i += 1
            else:
                return -1
        else:
            i += 1
    return buckets

print(min_buckets(".H.H."))
print(min_buckets("H..H"))
print(min_buckets(".HHH."))
public class Hamsters {
    public static int minBuckets(String hamsters) {
        int buckets = 0;
        int n = hamsters.length();
        for (int i = 0; i < n; ++i) {
            if (hamsters.charAt(i) == 'H') {
                if (i + 1 < n && hamsters.charAt(i + 1) == '.') {
                    buckets++;
                    i += 2;
                } else if (i > 0 && hamsters.charAt(i - 1) == '.') {
                    buckets++;
                } else {
                    return -1;
                }
            }
        }
        return buckets;
    }
    
    public static void main(String[] args) {
        System.out.println(minBuckets(".H.H."));
        System.out.println(minBuckets("H..H"));
        System.out.println(minBuckets(".HHH."));
    }
}
#include <iostream>
#include <string>
using namespace std;

int minBuckets(string hamsters) {
    int buckets = 0;
    int n = hamsters.size();
    for (int i = 0; i < n; ++i) {
        if (hamsters[i] == 'H') {
            if (i + 1 < n && hamsters[i + 1] == '.') {
                buckets++;
                i += 2;
            } else if (i > 0 && hamsters[i - 1] == '.') {
                buckets++;
            } else {
                return -1;
            }
        }
    }
    return buckets;
}

int main() {
    cout << minBuckets(".H.H.") << endl;
    cout << minBuckets("H..H") << endl;
    cout << minBuckets(".HHH.") << endl;
    return 0;
}
function minBuckets(hamsters) {
    let buckets = 0;
    let n = hamsters.length;

    for (let i = 0; i < n; i++) {
        if (hamsters[i] === 'H') {
            if (i + 1 < n && hamsters[i + 1] === '.') {
                buckets++;
                i += 2;
            } else if (i > 0 && hamsters[i - 1] === '.') {
                buckets++;
            } else {
                return -1;
            }
        }
    }
    return buckets;
}

console.log(minBuckets(".H.H."));
console.log(minBuckets("H..H"));
console.log(minBuckets(".HHH."));
#include <stdio.h>
#include <string.h>

int minBuckets(const char* hamsters) {
    int n = strlen(hamsters);
    int buckets = 0;
    for (int i = 0; i < n; i++) {
        if (hamsters[i] == 'H') {
            if (i + 1 < n && hamsters[i + 1] == '.') {
                buckets++;
                i += 2;
            } else if (i > 0 && hamsters[i - 1] == '.') {
                buckets++;
            } else {
                return -1;
            }
        }
    }
    return buckets;
}

int main() {
    printf("%d\n", minBuckets(".H.H."));
    printf("%d\n", minBuckets("H..H"));
    printf("%d\n", minBuckets(".HHH."));
    return 0;
}
using System;

public class Hamsters {
    public static int MinBuckets(string hamsters) {
        int buckets = 0;
        int n = hamsters.Length;
        for (int i = 0; i < n; ++i) {
            if (hamsters[i] == 'H') {
                if (i + 1 < n && hamsters[i + 1] == '.') {
                    buckets++;
                    i += 2;
                } else if (i > 0 && hamsters[i - 1] == '.') {
                    buckets++;
                } else {
                    return -1;
                }
            }
        }
        return buckets;
    }

    public static void Main(string[] args) {
        Console.WriteLine(MinBuckets(".H.H."));
        Console.WriteLine(MinBuckets("H..H"));
        Console.WriteLine(MinBuckets(".HHH."));
    }
}

This Python solution involves traversing the input string character by character. The goal is to place as few buckets as possible while ensuring every hamster 'H' is fed. Hence, we prioritize placing a bucket to the right if possible. If that's not possible, we resort to placing one to the left. If neither option is available, feeding all hamsters is not feasible.

Complexity

Time Complexity: O(n), where n is the length of the string.
Space Complexity: O(1).

Try this approach in the editor

Approach 2: Two-Pass Strategy

This approach entails two traversals of the string. The first pass places initial buckets optimally, focusing on right-side placements. The second pass revisits earlier decisions, adjusting by potentially placing missing left-side buckets if needed, ensuring all hamsters receive feed.

def min_buckets(hamsters: str) -> int:
    n = len(hamsters)
    buckets = 0
    visited = [False] * n

    # First pass
    for i in range(n):
        if hamsters[i] == 'H' and i + 1 < n and hamsters[i + 1] == '.':
            buckets += 1
            visited[i + 1] = True

    # Second pass
    for i in range(n):
        if hamsters[i] == 'H' and not visited[i] and i > 0 and hamsters[i - 1] == '.':
            buckets += 1
        elif hamsters[i] == 'H' and not visited[i]:
            return -1

    return buckets

print(min_buckets(".H.H."))
print(min_buckets("H..H"))
print(min_buckets(".HHH."))
public class Hamsters {
    public static int minBuckets(String hamsters) {
        int n = hamsters.length();
        int buckets = 0;
        boolean[] visited = new boolean[n];

        for (int i = 0; i < n; ++i) {
            if (hamsters.charAt(i) == 'H' && i + 1 < n && hamsters.charAt(i + 1) == '.') {
                buckets++;
                visited[i + 1] = true;
            }
        }

        for (int i = 0; i < n; ++i) {
            if (hamsters.charAt(i) == 'H' && !visited[i] && i > 0 && hamsters.charAt(i - 1) == '.') {
                buckets++;
            } else if (hamsters.charAt(i) == 'H' && !visited[i]) {
                return -1;
            }
        }

        return buckets;
    }

    public static void main(String[] args) {
        System.out.println(minBuckets(".H.H."));
        System.out.println(minBuckets("H..H"));
        System.out.println(minBuckets(".HHH."));
    }
}
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int minBuckets(string hamsters) {
    int n = hamsters.size();
    int buckets = 0;
    vector<int> visited(n, 0);

    for (int i = 0; i < n; ++i) {
        if (hamsters[i] == 'H' && i + 1 < n && hamsters[i + 1] == '.') {
            buckets++;
            visited[i + 1] = 1;
        }
    }

    for (int i = 0; i < n; ++i) {
        if (hamsters[i] == 'H' && !visited[i] && i > 0 && hamsters[i - 1] == '.') {
            buckets++;
        } else if (hamsters[i] == 'H' && !visited[i]) {
            return -1;
        }
    }

    return buckets;
}

int main() {
    cout << minBuckets(".H.H.") << endl;
    cout << minBuckets("H..H") << endl;
    cout << minBuckets(".HHH.") << endl;
    return 0;
}
function minBuckets(hamsters) {
    let n = hamsters.length;
    let buckets = 0;
    let visited = Array(n).fill(false);

    // First pass
    for (let i = 0; i < n; i++) {
        if (hamsters[i] === 'H' && i + 1 < n && hamsters[i + 1] === '.') {
            buckets++;
            visited[i + 1] = true;
        }
    }

    // Second pass
    for (let i = 0; i < n; i++) {
        if (hamsters[i] === 'H' && !visited[i] && i > 0 && hamsters[i - 1] === '.') {
            buckets++;
        } else if (hamsters[i] === 'H' && !visited[i]) {
            return -1;
        }
    }

    return buckets;
}

console.log(minBuckets(".H.H."));
console.log(minBuckets("H..H"));
console.log(minBuckets(".HHH."));
#include <stdio.h>
#include <string.h>

int minBuckets(const char* hamsters) {
    int n = strlen(hamsters);
    int buckets = 0;
    int visited[n];
    memset(visited, 0, sizeof(visited));

    for (int i = 0; i < n; i++) {
        if (hamsters[i] == 'H' && i + 1 < n && hamsters[i + 1] == '.') {
            buckets++;
            visited[i + 1] = 1;
        }
    }

    for (int i = 0; i < n; i++) {
        if (hamsters[i] == 'H' && !visited[i] && i > 0 && hamsters[i - 1] == '.') {
            buckets++;
        } else if (hamsters[i] == 'H' && !visited[i]) {
            return -1;
        }
    }

    return buckets;
}

int main() {
    printf("%d\n", minBuckets(".H.H."));
    printf("%d\n", minBuckets("H..H"));
    printf("%d\n", minBuckets(".HHH."));
    return 0;
}
using System;

public class Hamsters {
    public static int MinBuckets(string hamsters) {
        int n = hamsters.Length;
        int buckets = 0;
        bool[] visited = new bool[n];

        for (int i = 0; i < n; i++) {
            if (hamsters[i] == 'H' && i + 1 < n && hamsters[i + 1] == '.') {
                buckets++;
                visited[i + 1] = true;
            }
        }

        for (int i = 0; i < n; i++) {
            if (hamsters[i] == 'H' && !visited[i] && i > 0 && hamsters[i - 1] == '.') {
                buckets++;
            } else if (hamsters[i] == 'H' && !visited[i]) {
                return -1;
            }
        }

        return buckets;
    }

    public static void Main(string[] args) {
        Console.WriteLine(MinBuckets(".H.H."));
        Console.WriteLine(MinBuckets("H..H"));
        Console.WriteLine(MinBuckets(".HHH."));
    }
}

This Python approach performs similarly through a dual pass method, using a list `visited` to monitor previous bucket placements. The first pass aims for optimum surrounding bucket coverage. Then, the second pass validates coverage to assure complete needs are addressed or determines an impossibility condition.

Complexity

Time Complexity: O(n), where n is the length of the string.
Space Complexity: O(n), with `visited` list.

Try this approach in the editor

Approach 3: Default Approach

func minimumBuckets(street string) int {
	ans, n := 0, len(street)
	for i := 0; i < n; i++ {
		if street[i] == 'H' {
			if i+1 < n && street[i+1] == '.' {
				ans++
				i += 2
			} else if i > 0 && street[i-1] == '.' {
				ans++
			} else {
				return -1
			}
		}
	}
	return ans
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Greedy Approach

Time Complexity: O(n), where n is the length of the string.
Space Complexity: O(1).

Two-Pass Strategy

Time Complexity: O(n), where n is the length of the string.
Space Complexity: O(n), with `visited` list.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Greedy PlacementO(n)O(1)Best general solution. Minimal logic with optimal bucket sharing.
Two-Pass StrategyO(n)O(n)Useful when separating forced placements from optimal placements for clarity.

Frequently asked questions

Is Minimum Number of Food Buckets to Feed the Hamsters easy or hard?

This problem is usually categorized as Medium difficulty. The implementation is simple once the greedy rule is discovered, but recognizing the optimal placement strategy and handling edge cases like consecutive hamsters can be tricky.

Minimum Number of Food Buckets to Feed the Hamsters Python/Java solution

Python and Java implementations typically follow the same greedy rule: iterate through the string, prefer placing buckets to the right of each hamster, otherwise use the left side. Both implementations run in O(n) time and use O(1) additional space.

How to solve Minimum Number of Food Buckets to Feed the Hamsters in O(n)?

Traverse the string once and handle each hamster immediately. If the right adjacent cell is empty, place a bucket there to maximize sharing with future hamsters. If not, check the left side. If both sides are blocked, feeding all hamsters is impossible and the answer is -1. This single pass guarantees O(n) time.

What is the best approach for Minimum Number of Food Buckets to Feed the Hamsters?

The greedy approach is the best solution. Scan the string from left to right and place a bucket to the right of each hamster whenever possible so it can potentially feed the next hamster too. If the right side is unavailable, place it on the left. This strategy guarantees the minimum number of buckets with O(n) time and O(1) space.

Is Minimum Number of Food Buckets to Feed the Hamsters asked at Google/Amazon/Meta?

Problems with greedy placement and string scanning patterns appear frequently in interviews at companies like Amazon, Google, and Meta. Variations of this problem test whether candidates can identify local optimal decisions that lead to a global optimum.

What data structure is used in Minimum Number of Food Buckets to Feed the Hamsters?

The core structure is a string representing the street. The greedy solution only uses simple index traversal and constant variables, while the two-pass strategy may use an auxiliary array to track bucket placements.

What is the time complexity of Minimum Number of Food Buckets to Feed the Hamsters?

The optimal greedy solution runs in O(n) time where n is the length of the street string because each position is processed once. Space complexity is O(1) since only a few variables are used to track placements without extra data structures.

Comments

Now write it yourselfClose this page and solve Minimum Number of Food Buckets to Feed the Hamsters in the editor, without looking.
Practise Minimum Number of Food Buckets to Feed the Hamsters