Problem · Array

Nested List Iterator with Remove

Learn this problem
MediumAirbnb logoAirbnbFULLTIMEPHONE SCREEN

Problem statement

You are given a mutable nested sequence lists, represented as an array of integer arrays, and a finite array operations. Simulate an iterator that visits the integers in row-major order.

The supported operations follow these rules:

  • HAS_NEXT returns whether another integer exists. It skips empty and exhausted rows, consumes no integer, and may be called repeatedly.
  • NEXT returns the next integer. If the iterator is exhausted, it throws a no-next-element error.
  • REMOVE deletes from lists the value returned by the most recent successful NEXT. It may succeed at most once for that successful NEXT. Calling it before any successful NEXT, or calling it twice for the same result, throws an illegal-remove error.

A failed NEXT does not revoke the still-unused removal right from the most recent successful NEXT. Calling HAS_NEXT also does not revoke that right. When removal happens in the row currently being scanned, adjust the row cursor so the element that shifted into the removed position is not skipped.

Finite operation adapter

Return one string for every operation, followed by one final state string:

  • HAS_NEXT contributes "true" or "false".
  • A successful NEXT contributes the returned integer in decimal form; an exhausted call contributes "ERROR:no-next".
  • A successful REMOVE contributes "removed"; an illegal call contributes "ERROR:remove".
  • The last result is "STATE:" followed by the final nested arrays in compact JSON notation, including empty rows.

Function

runNestedIterator(lists: int[][], operations: String[]) → String[]

Examples

Example 1

lists = [[1,2],[],[3]]operations = ["HAS_NEXT","HAS_NEXT","NEXT","REMOVE","HAS_NEXT","NEXT","NEXT","HAS_NEXT"]return = ["true","true","1","removed","true","2","3","false","STATE:[[2],[],[3]]"]

The repeated checks do not consume 1. Removing 1 shifts 2 into column zero, so the cursor moves back and 2 remains the next value. The empty middle row is skipped.

Example 2

lists = [[5],[],[6,7]]operations = ["REMOVE","NEXT","HAS_NEXT","REMOVE","NEXT","REMOVE","REMOVE","NEXT","NEXT"]return = ["ERROR:remove","5","true","removed","6","removed","ERROR:remove","7","ERROR:no-next","STATE:[[],[],[7]]"]

The first removal is illegal. After 5, HAS_NEXT advances across the empty row to find 6, but removing 5 is still legal. Removing 6 adjusts the cursor so 7 is not skipped.

Example 3

lists = [[9]]operations = ["NEXT","NEXT","REMOVE","HAS_NEXT"]return = ["9","ERROR:no-next","removed","false","STATE:[[]]"]

The failed second NEXT does not consume a value or revoke the unused removal right for 9. Removing it leaves the sole row empty.

Constraints

  • 0 <= lists.length <= 1000
  • Each row may be empty, and the total number of integers is at most 5000.
  • Every integer is in [-10^9, 10^9].
  • 1 <= operations.length <= 5000
  • Every operation is HAS_NEXT, NEXT, or REMOVE.
  • The returned array has exactly operations.length + 1 strings.

More Airbnb problems

drafts saved locally
public String[] runNestedIterator(int[][] lists, String[] operations) {
    // Write your code here.
}
lists[[1,2],[],[3]]
operations["HAS_NEXT","HAS_NEXT","NEXT","REMOVE","HAS_NEXT","NEXT","NEXT","HAS_NEXT"]
expected["true", "true", "1", "removed", "true", "2", "3", "false", "STATE:2", "", "3"]
checking account