A greedy guide for determining whether a given number of flowers can be planted without violating the no-adjacent-flowers rule.
Problem Restatement
We are given a flowerbed represented by a binary array.
| Value | Meaning |
|---|---|
0 | Empty plot |
1 | A flower is already planted |
Flowers cannot be planted in adjacent plots.
We are also given an integer n.
We need to determine whether it is possible to plant n new flowers in the flowerbed without violating the no-adjacent-flowers rule.
The official problem states that no two flowers can be planted in adjacent plots and asks whether n new flowers can be planted.
Input and Output
Function signature:
def canPlaceFlowers(flowerbed: list[int], n: int) -> bool:
...Input:
| Parameter | Meaning |
|---|---|
flowerbed | Binary array representing plots |
n | Number of new flowers to plant |
Output:
| Type | Meaning |
|---|---|
bool | True if we can plant n flowers, otherwise False |
Examples
Example 1:
flowerbed = [1, 0, 0, 0, 1]
n = 1We can plant one flower at index 2:
[1, 0, 1, 0, 1]So the answer is:
TrueExample 2:
flowerbed = [1, 0, 0, 0, 1]
n = 2After planting at index 2, no more valid positions remain.
So the answer is:
FalseExample 3:
flowerbed = [0, 0, 0, 0, 0]
n = 3We can plant at indices:
0, 2, 4Final flowerbed:
[1, 0, 1, 0, 1]So the answer is:
TrueFirst Thought: Try Every Combination
One possible approach is to try all possible ways to place flowers and check whether any arrangement works.
This quickly becomes expensive because each empty plot creates another decision:
| Choice | Meaning |
|---|---|
| Plant here | Use the plot |
| Skip here | Leave the plot empty |
That creates exponential branching.
We need something simpler.
Key Insight
A flower should always be planted as early as possible whenever it is safe.
Suppose we are at index i.
We can plant a flower there if:
- The current plot is empty.
- The left neighbor is empty or does not exist.
- The right neighbor is empty or does not exist.
That condition is:
flowerbed[i] == 0
and left_is_empty
and right_is_emptyIf planting is allowed, planting immediately is always safe because planting later never creates more available space.
This leads to a greedy solution.
Algorithm
Scan the array from left to right.
For each position:
- Check whether the current plot is empty.
- Check whether the left side is safe.
- Check whether the right side is safe.
- If all conditions are satisfied:
- Plant a flower.
- Decrease
n.
- If
nbecomes0, returnTrue.
After the scan finishes:
- Return whether
n <= 0.
Implementation
class Solution:
def canPlaceFlowers(self, flowerbed: list[int], n: int) -> bool:
length = len(flowerbed)
for i in range(length):
if flowerbed[i] == 1:
continue
left_empty = (i == 0 or flowerbed[i - 1] == 0)
right_empty = (i == length - 1 or flowerbed[i + 1] == 0)
if left_empty and right_empty:
flowerbed[i] = 1
n -= 1
if n == 0:
return True
return n <= 0Code Explanation
We first store the array length:
length = len(flowerbed)Then we scan every position:
for i in range(length):If the current plot already contains a flower, we skip it:
if flowerbed[i] == 1:
continueNext, we check the left side:
left_empty = (i == 0 or flowerbed[i - 1] == 0)The first plot has no left neighbor, so it is automatically safe.
We also check the right side:
right_empty = (i == length - 1 or flowerbed[i + 1] == 0)The last plot has no right neighbor, so it is automatically safe.
If both sides are safe, we plant a flower:
if left_empty and right_empty:
flowerbed[i] = 1
n -= 1We update the flowerbed immediately so later positions see the new flower.
If all required flowers are planted, we return early:
if n == 0:
return TrueAt the end, we return whether enough flowers were planted:
return n <= 0Correctness
The algorithm scans the flowerbed from left to right.
At each position, it plants a flower exactly when doing so does not violate the adjacency rule. Therefore, every planted flower is valid.
Now consider any position where the algorithm plants a flower. Planting there cannot reduce the total number of flowers that can eventually be planted.
Why?
Because if a position is valid now, delaying the placement cannot create additional free neighboring plots later. The current position already blocks at most its two neighbors. Any future flower placement would face the same restriction.
Therefore, planting greedily as early as possible never harms the optimal solution.
The algorithm plants a flower at every valid earliest position. So if the algorithm cannot plant n flowers, then no valid arrangement can.
Therefore, the algorithm returns True exactly when it is possible to plant n flowers.
Complexity
Let m be the length of the flowerbed.
| Metric | Value | Why |
|---|---|---|
| Time | O(m) | We scan the array once |
| Space | O(1) | Only a few variables are used |
Alternative Without Modifying Input
Some versions prefer not to modify the original array.
We can keep the same logic while tracking placements separately.
class Solution:
def canPlaceFlowers(self, flowerbed: list[int], n: int) -> bool:
count = 0
length = len(flowerbed)
for i in range(length):
if flowerbed[i] == 1:
continue
left_empty = (i == 0 or flowerbed[i - 1] == 0)
right_empty = (
i == length - 1
or flowerbed[i + 1] == 0
)
if left_empty and right_empty:
count += 1
flowerbed[i] = 1
return count >= nThis still updates the array internally, but it separates the planted count from the input parameter n.
Testing
def run_tests():
s = Solution()
assert s.canPlaceFlowers([1, 0, 0, 0, 1], 1) is True
assert s.canPlaceFlowers([1, 0, 0, 0, 1], 2) is False
assert s.canPlaceFlowers([0, 0, 0, 0, 0], 3) is True
assert s.canPlaceFlowers([1], 0) is True
assert s.canPlaceFlowers([0], 1) is True
assert s.canPlaceFlowers([1], 1) is False
assert s.canPlaceFlowers([0, 0], 1) is True
assert s.canPlaceFlowers([0, 0], 2) is False
print("all tests passed")
run_tests()Test coverage:
| Case | Why |
|---|---|
| Basic valid placement | Confirms core logic |
| Impossible placement | Confirms rejection |
| All empty plots | Checks maximum placement |
| Single-element arrays | Boundary condition |
| Two-element arrays | Adjacent edge handling |