← TikTok Interview Insights

TikTok·Machine Learning Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
Jul 2026Remote

Summary

TikTok ML Engineer interview that leaned harder into algorithms than I expected. The whole session basically lived inside one problem but they kept pulling threads on it until I was pretty much out of answers.

Questions Asked (4)

Q1

Given an integer array, find the length of the longest strictly increasing subsequence and output one valid subsequence. They wanted an O(n log n) solution using binary search, and asked you to walk through the patience sorting idea and explain how reconstruction works.

Algorithms & Data Structures
Author's notes

I knew LIS and had done the O(n^2) version before, but the O(n log n) path with patience sorting was something I'd only half-remembered.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the O(n^2) dynamic programming approach to establish the problem, then introduce the patience sorting method with binary search to achieve O(n log n). Emphasize that the tails array does not directly store the LIS, but by keeping track of predecessor indices during updates, you can reconstruct one valid subsequence.

Pro tip: Mention that the tails array is not the LIS itself, but a tool to compute the length; reconstruction requires storing parent pointers. Also, clarify that binary search is used to find the first element in tails that is >= current number (lower_bound) for strictly increasing.

1. Clarify the problem and constraints

Confirm that the subsequence must be strictly increasing and that we need both the length and one valid subsequence. Discuss edge cases like empty array or all decreasing.

2. Explain the O(n^2) DP approach

Briefly describe the dynamic programming solution where dp[i] is the length of LIS ending at i, and parent pointers for reconstruction. This sets the stage for optimization.

3. Introduce patience sorting with binary search

Describe maintaining a tails array where tails[k] is the smallest tail of an increasing subsequence of length k+1. For each number, use binary search to find its position and update tails, achieving O(n log n).

4. Explain reconstruction with parent pointers

During the process, store for each element its predecessor index (the index of the previous element in the subsequence). After processing, backtrack from the index of the last element of the LIS to build the subsequence.

5. Walk through a small example

Use a simple array like [10,9,2,5,3,7,101,18] to illustrate the algorithm step by step, showing tails updates and parent pointers, and finally reconstruct the LIS.

Key Points to Mention

  • Binary search should find the first element in tails that is >= current number (lower_bound) to maintain strict increase.
  • The tails array length gives the LIS length, but tails itself is not necessarily a valid subsequence.
  • Parent pointers (or predecessor indices) are essential for reconstructing one valid LIS.
  • Time complexity is O(n log n) due to binary search per element; space complexity is O(n) for tails and parent arrays.
  • Handling duplicates: for strictly increasing, use lower_bound; for non-decreasing, use upper_bound.
  • Edge cases: empty array returns 0 and empty subsequence; all elements equal returns length 1.

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

Q2

How would you adapt the solution to handle non-decreasing subsequences instead of strictly increasing ones, and what changes are needed when duplicates are present?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Seemed like a small tweak but I second-guessed myself on which direction to shift the binary search boundary.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the original problem (likely LIS) and then explain how to adapt it for non-decreasing subsequences by changing the comparison from strict inequality to non-strict. Discuss the impact on the O(n log n) patience sorting approach, particularly how duplicates are handled with upper_bound vs lower_bound, and mention edge cases and complexity.

Pro tip: Emphasize that using upper_bound for non-decreasing LIS is crucial because it allows equal elements to extend the subsequence, and note that this change does not affect the overall time complexity. Also, mention that for strictly increasing LIS, lower_bound is used, and the difference is subtle but important.

1. Restate the original problem

Briefly describe the standard LIS problem and the typical O(n log n) solution using patience sorting with binary search.

2. Adapt for non-decreasing

Explain that to allow non-decreasing subsequences, we change the comparison from strict to non-strict, which means when we find the first element greater than the current, we replace it (using upper_bound instead of lower_bound).

3. Handle duplicates

Discuss how duplicates are naturally handled: with upper_bound, equal elements can extend the subsequence, so duplicates are included. Also, note that the algorithm remains O(n log n).

4. Consider edge cases and alternatives

Mention edge cases like all elements equal, and briefly note alternative approaches (e.g., DP with O(n^2)) and why the optimized approach is preferred.

Key Points to Mention

  • Difference between lower_bound and upper_bound in binary search for LIS.
  • Time complexity remains O(n log n) for non-decreasing LIS.
  • Duplicates are allowed and can be part of the subsequence.
  • Patience sorting algorithm and how it maintains the tails array.
  • Edge case: all elements equal yields LIS length equal to array length.
  • Potential pitfalls: using strict comparison would incorrectly exclude duplicates.

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

Q3

How would you count the total number of distinct longest increasing subsequences in the array?

Algorithms & Data Structures
Author's notes

Didn't see this coming at all.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Use dynamic programming to compute the length of the longest increasing subsequence (LIS) ending at each index, and simultaneously track the number of distinct LIS ending at that index. Then, after processing all elements, sum the counts for indices where the LIS length equals the global maximum.

Pro tip: Clarify what 'distinct' means: typically it refers to distinct index sequences, not distinct values. If the array has duplicates, ensure your DP handles them correctly by only extending from strictly smaller elements.

1. Define DP state

Let dp[i] be the length of the LIS ending at index i, and count[i] be the number of distinct LIS of length dp[i] ending at index i. Initialize dp[i]=1 and count[i]=1 for all i.

2. Fill DP tables

For each i from 0 to n-1, iterate j from 0 to i-1. If nums[j] < nums[i], then if dp[j]+1 > dp[i], update dp[i] = dp[j]+1 and count[i] = count[j]; else if dp[j]+1 == dp[i], add count[j] to count[i].

3. Find global LIS length

After filling the tables, compute maxLen = max(dp[i]) over all i.

4. Sum counts for max length

Sum count[i] for all i where dp[i] == maxLen. This sum is the total number of distinct LIS.

5. Handle duplicates and edge cases

If the array has duplicate values, ensure that only strictly increasing subsequences are counted. Also handle empty array (return 0) and single element (return 1).

Key Points to Mention

  • Time complexity O(n^2) and space complexity O(n) for the DP approach.
  • Definition of 'distinct': distinct index sequences, not distinct values.
  • Handling of duplicates: only extend when nums[j] < nums[i] to ensure strict increase.
  • Initialization: dp[i]=1, count[i]=1 for each element.
  • Summing counts only for indices where dp[i] equals the global maximum length.
  • Potential optimization using Fenwick tree or segment tree for O(n log n) if needed, but O(n^2) is acceptable for clarity.

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

Q4

Walk through the time and space complexity of your O(n log n) LIS approach.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Easy part of the whole interview.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clearly stating the algorithm: patience sorting with binary search. Then break down the time complexity: O(n log n) due to n iterations each with a binary search on the tails array. For space, explain that the tails array can grow up to O(n) in the worst case, but often less.

Pro tip: Mention that while the time complexity is O(n log n), the space can be optimized to O(k) where k is the length of the LIS, and in practice for many sequences it's much smaller than n. Also, note that this approach only gives the length, not the actual subsequence, unless additional tracking is used.

1. State the algorithm

Briefly describe the O(n log n) LIS algorithm: maintain a tails array where tails[i] is the smallest tail of an increasing subsequence of length i+1. For each element, binary search to find its position and update tails.

2. Analyze time complexity

Explain that we iterate through n elements, and for each we perform a binary search on the tails array, which takes O(log n) time. Thus total time is O(n log n).

3. Analyze space complexity

The tails array can have at most n elements, so space is O(n) in the worst case. However, it only stores the minimal tails, so its size equals the length of the LIS, which could be smaller.

4. Discuss trade-offs and edge cases

Mention that this approach is optimal for comparison-based LIS. Also note that if we need to reconstruct the subsequence, we need additional O(n) space for parent pointers, but the time remains O(n log n).

Key Points to Mention

  • Patience sorting / binary search on tails array
  • Time: O(n log n) because n iterations * O(log n) binary search
  • Space: O(n) worst-case for tails array, but often O(LIS length)
  • Comparison-based lower bound: O(n log n) is optimal
  • Reconstruction requires extra space and careful handling
  • Edge cases: empty array, strictly increasing/decreasing sequences

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