Problem Description
You are given a circular street of houses (with at most k houses). You can only interact with the street via three operations on the current house: • closeDoor() – to close the door of the current house, • isDoorOpen() – to check whether the house’s door is open, • moveRight() – to proceed to the next house on the right. At least one door is open initially. Starting from an arbitrary house, your task is to count (determine) the total number of houses on the street. Note that the street is circular – after the last house, the next house is the first one.
Key Insights
- Since the street is circular, performing a fixed number of moves (equal to the number of houses) will bring you back to where you started.
- However, you do not initially know the number of houses n (with n ≤ k). It is possible that many doors are already closed.
- The only “write” operation is closeDoor(), so you cannot “mark” a house by toggling it if it was originally closed. Thus we must first “tag” a house that is guaranteed to be open.
- The solution uses a two‐phase approach: • In the first phase (doubling phase) you mark a uniquely “tagged” house (by ensuring you only close a door that was open when you encountered it) and then repeatedly “jump” by an increasing number of moves (doubling the distance) until you hit back the tagged house. • In the second phase you perform a binary search between the last safe “jump” distance and the first “jump” that overshoots (i.e. lands on the tagged house) in order to determine the exact count n.
- A helper routine is used to “test” whether a given number of moves from the tag returns to the tagged house. Although the street contains other closed doors (which could have been originally closed), you assume that by being careful the door you closed for your tag is distinguishable (see “gotcha” below).
Space and Time Complexity
Time Complexity: O(n + log k) in the worst‐case. In the worst case the doubling phase walks several partial rounds and the binary search phase “walks” back to the starting marker, but n is O(k). Space Complexity: O(1) (only a few pointers/counters are used).
Solution
The idea is to “mark” one house in a way that you can later identify it. To do this, if the door you face is open you call closeDoor() so that it is closed by your own action (if it was originally closed, you first move right until you find an open door). This house becomes your marker. Next, we “jump” an increasing number of houses (using doubling – 1, 2, 4, 8, …) until a jump leads you to the marker (that is, when isDoorOpen() returns false at your jump destination). Since many houses may be closed originally, our algorithm implicitly relies on the fact that the marker is the only door we themselves have closed. (In an interview you should clearly explain that one “gotcha” is that we assume we can distinguish a door we closed from a door that was originally closed; this is a common trick used in these stylized problems.) Once the doubling phase establishes an interval [low, high] such that moving ‘low’ moves from the marker does NOT give the marker but moving ‘high’ moves DOES, you can use binary search. In order to “test” a candidate distance, a helper routine simulates moving that many houses starting from the marker, checks the door state (open means you haven’t come full circle yet; closed means that you reached the marker), and then continues moving to return to the marker (since the street is circular, eventually you will see the marker again). Combining both phases, you determine the exact number of houses n.
Code Solutions
Below are sample implementations in Python, JavaScript, C++ and Java. They assume the existence of a Street class with the three provided methods. Comments on each line explain the rationale.