Solve path normalization and nested iterator
Company: Bridge
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency in string/path normalization, manipulation of hierarchical data structures, stack-based iterator design, lazy versus eager flattening strategies, and algorithmic time/space complexity analysis in the Coding & Algorithms domain.
Normalize Unix-Style Absolute Path
Constraints
- 1 <= path.length
- path consists of English letters, digits, '.', '/' and '_'
- path is an absolute Unix path that begins with '/'
Examples
Input: ('/home/',)
Expected Output: '/home'
Explanation: Trailing slash is removed.
Input: ('/../',)
Expected Output: '/'
Explanation: '..' at the root is ignored, leaving the root '/'.
Input: ('/home//foo/',)
Expected Output: '/home/foo'
Explanation: The double slash collapses to a single separator and the trailing slash is dropped.
Input: ('/a/./b/../../c/',)
Expected Output: '/c'
Explanation: '.' is skipped, 'b' is popped by the first '..', 'a' is popped by the second '..', leaving '/c'.
Input: ('/',)
Expected Output: '/'
Explanation: The root path is already canonical.
Input: ('/a/../../b/../c//.//',)
Expected Output: '/c'
Explanation: 'a' is popped, the extra '..' at root is ignored, 'b' is popped, leaving '/c'.
Input: ('/...',)
Expected Output: '/...'
Explanation: '...' is a valid directory name (not '.' or '..'), so it is kept.
Hints
- Split the string on '/'. Empty strings (from '//' or leading/trailing slashes) and '.' can be skipped entirely.
- Use a stack of directory names. On '..', pop one entry if the stack is non-empty (this naturally handles '..' at root by doing nothing).
- Rebuild the answer as '/' + '/'.join(stack); an empty stack yields the root '/'.
Flatten a Nested List Iterator
Constraints
- 0 <= total number of integers
- Each leaf value fits in a 32-bit signed integer
- Nesting may be arbitrarily deep but is finite
Examples
Input: ([[1, 1], 2, [1, 1]],)
Expected Output: [1, 1, 2, 1, 1]
Explanation: Left-to-right flattening of two sublists around a bare integer.
Input: ([1, [4, [6]]],)
Expected Output: [1, 4, 6]
Explanation: Deeper nesting: 6 lives two levels down but still emits in order.
Input: ([],)
Expected Output: []
Explanation: Empty input yields no integers.
Input: ([[]],)
Expected Output: []
Explanation: A single empty sublist contains no integers.
Input: ([[], [], []],)
Expected Output: []
Explanation: Several empty sublists still produce nothing.
Input: ([5],)
Expected Output: [5]
Explanation: Single integer.
Input: ([[[[7]]], 8, [[-3, 0]]],)
Expected Output: [7, 8, -3, 0]
Explanation: Mix of deep nesting, negatives and zero, preserved in order.
Input: ([1, [], 2, [[], [3]], 4],)
Expected Output: [1, 2, 3, 4]
Explanation: Empty sublists are skipped lazily while real integers emit in order.
Hints
- Push the top-level elements onto a stack in reverse order so the leftmost element ends up on top.
- Before answering hasNext(), repeatedly pop any list on top of the stack and push its children in reverse order until an integer surfaces (this is the lazy part).
- next() simply pops the now-guaranteed integer. Compared to eager flattening, this avoids touching elements you never iterate to and uses space proportional to depth, not to the total count.