← Grammarly Interview Insights

Grammarly·Software Engineer·Technical Phone Screen·Intermediate

IntermediatePrefer not to say
May 2026

Summary

Coding round at Grammarly for a Software Engineer position. Two algorithm problems, one with a follow-up variant that made things more interesting. Nothing too wild but the stack-based string problem had a tricky extension I had to think through carefully.

Questions Asked (2)

Q1

Given a string, repeatedly remove adjacent pairs of equal characters until none remain. Then, as a follow-up, generalize this to removing groups of k adjacent equal characters.

Algorithms & Data Structures
Author's notes

The basic version I got pretty quickly, stack-based approach where you track characters and pop when there's a match.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem and edge cases, then propose a stack-based solution for the base case (k=2) and extend it to a generalized stack that tracks character counts. Discuss time and space complexity, and consider alternative approaches like recursion or two-pointer for completeness.

Pro tip: Mention that the stack approach naturally handles the follow-up by storing (char, count) pairs, and that you can optimize by only pushing when count > 0. Also, note that the problem is similar to 'remove adjacent duplicates' and can be solved in O(n) time.

1. Clarify requirements and edge cases

Ask if the removal should be done iteratively until no more pairs exist, and confirm that k is a positive integer. Discuss edge cases like empty string, no removals, and all characters removed.

2. Propose stack-based solution for k=2

Use a stack to process characters one by one: if the top of the stack equals the current character, pop; otherwise, push. This simulates the removal of adjacent equal pairs in O(n) time.

3. Generalize to k using stack of (char, count)

Modify the stack to store pairs of (character, consecutive count). When the current character matches the top's character, increment its count; if the count reaches k, pop the pair. Otherwise, push a new pair with count 1.

4. Analyze complexity and discuss optimizations

Explain that the algorithm runs in O(n) time and O(n) space in the worst case. Mention that the stack size is bounded by the number of distinct character groups, and that no extra passes are needed.

5. Test with examples and consider alternatives

Walk through a few examples (e.g., 'abbaca' for k=2, 'deeedbbcccbdaa' for k=3) to verify correctness. Briefly mention alternative approaches like recursion or two-pointer, but highlight the stack's efficiency.

Key Points to Mention

  • Stack data structure for O(n) time complexity
  • Handling the follow-up by storing character counts in the stack
  • Edge cases: empty string, no removals, all characters removed
  • Time and space complexity analysis
  • Comparison with naive repeated scanning approach (O(n^2))
  • Potential for in-place modification if using a mutable array as stack

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Design a time-based key-value store that supports set(key, value, timestamp) and get(key, timestamp), where get returns the value at the largest timestamp less than or equal to the queried one.

Algorithms & Data StructuresSystem Design
Author's notes

I knew binary search was the move here since timestamps are strictly increasing per key, so you can just store a sorted list of (timestamp, value) pairs per key in a hashmap.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then propose a design using a hash map from key to a list of (timestamp, value) pairs, with binary search for get. Discuss trade-offs between time and space, and consider edge cases like multiple sets at the same timestamp.

Pro tip: Mention that timestamps are monotonically increasing per key, so you can append and binary search; also note that if the store is distributed, you'd need a different approach like a time-series database.

1. Clarify Requirements

Ask about expected scale, read/write ratio, timestamp granularity, and whether timestamps are unique per key. Confirm that get should return the value at the largest timestamp <= given timestamp.

2. Propose Data Structure

Use a hash map where each key maps to a list of (timestamp, value) pairs, sorted by timestamp. Since timestamps are increasing, appending maintains order.

3. Implement set and get

For set, append the new (timestamp, value) to the list for the key. For get, perform binary search on the list to find the largest timestamp <= the query timestamp, then return the corresponding value.

4. Analyze Complexity

Set is O(1) amortized, get is O(log n) where n is the number of timestamps for that key. Space is O(total number of set calls).

5. Discuss Edge Cases and Extensions

Handle cases where the key doesn't exist or no timestamp <= query. Discuss potential optimizations like using a balanced BST or skip list if timestamps are not monotonic, or if we need to delete old entries.

Key Points to Mention

  • Hash map for key to list of (timestamp, value) pairs
  • Binary search for efficient get operation
  • Timestamps are monotonically increasing per key, so appending maintains sorted order
  • Time complexity: O(1) for set, O(log n) for get
  • Space complexity: O(total number of set operations)
  • Edge cases: non-existent key, no timestamp <= query, multiple sets at same timestamp

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.