PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates understanding of subsequences, dynamic programming and algorithmic optimization for array processing, and is categorized under Coding & Algorithms; it emphasizes practical application of algorithm design and complexity analysis rather than purely theoretical knowledge.

  • medium
  • TikTok
  • Coding & Algorithms
  • Software Engineer

Compute length of longest increasing subsequence

Company: TikTok

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

You are given an integer array `nums` of length `n`. A **subsequence** of `nums` is a sequence that can be derived from `nums` by deleting zero or more elements without changing the order of the remaining elements. The elements of the subsequence do **not** need to be contiguous in the original array. A subsequence is called **strictly increasing** if every element is strictly greater than the previous one. **Task**: Return the length of the longest strictly increasing subsequence of `nums`. --- ### Example 1 Input: ```text nums = [10, 9, 2, 5, 3, 7, 101, 18] ``` One longest strictly increasing subsequence is `[2, 3, 7, 101]`, so the answer is `4`. Output: ```text 4 ``` ### Example 2 Input: ```text nums = [0, 1, 0, 3, 2, 3] ``` One longest strictly increasing subsequence is `[0, 1, 2, 3]`, so the answer is `4`. Output: ```text 4 ``` ### Example 3 Input: ```text nums = [7, 7, 7, 7] ``` Every strictly increasing subsequence has length `1` (any single element), so the answer is `1`. Output: ```text 1 ``` ```hint Start with the brute force There is an obvious $O(n^2)$ dynamic program: let $dp[i]$ be the length of the longest strictly increasing subsequence that **ends at index $i$**. Then $dp[i] = 1 + \max(dp[j])$ over all $j < i$ with $nums[j] < nums[i]$. The answer is $\max_i dp[i]$. Getting this right first clarifies the recurrence before you optimize. ``` ```hint Beating O(n^2) — the key insight To hit $O(n \log n)$, maintain an array `tails`, where `tails[k]` is the **smallest possible tail value** of any strictly increasing subsequence of length $k+1$ seen so far. This array is always sorted, which lets you binary-search it. Keeping tails as small as possible greedily maximizes the room for future extensions. ``` ```hint The per-element update For each `x = nums[i]`, binary-search `tails` for the **leftmost** position whose value is `>= x` (a lower-bound search). If found, overwrite it with `x` (you found a length-$k+1$ subsequence ending in a smaller tail). If `x` is larger than every tail, append it (you extended the longest run by one). The answer is the final length of `tails`. Note: lower-bound (`>= x`) enforces *strict* increase; an upper-bound (`> x`) would instead count non-decreasing subsequences — a classic off-by-one trap. ``` ```hint Edge cases to confirm A single-element array returns `1`. An all-equal array (Example 3) returns `1` because each repeat overwrites `tails[0]` rather than appending. Negative numbers and the full $[-10^9, 10^9]$ range need no special handling if comparisons use the raw integers. ``` --- ### Constraints & Assumptions - `1 <= n <= 2 * 10^5`, so an $O(n^2)$ solution (~$4 \times 10^{10}$ operations worst case) is too slow; aim for $O(n \log n)$. - `-10^9 <= nums[i] <= 10^9` — values fit in a 32-bit signed integer, but be mindful of language-specific overflow if you do arithmetic on them (here you only compare, so no overflow risk). - "Increasing" means **strictly** increasing; equal adjacent values do not extend a subsequence. - The array is non-empty, so the answer is always at least `1`. - You are asked only for the **length**, not the subsequence itself (though reconstruction is a natural follow-up). ### Clarifying Questions to Ask - Is the required ordering **strictly** increasing or **non-decreasing**? (This changes the binary-search bound from lower-bound to upper-bound.) - Do I need to return the actual subsequence, or just its length? - Can the array be empty, and if so what should I return? - Are there constraints on memory (e.g. is $O(n)$ extra space acceptable), and is the input mutable? - Could there be duplicate values, and how should ties be handled? (Confirms the strict-vs-non-decreasing decision.) ### What a Strong Answer Covers - **Correct recurrence**: states the $O(n^2)$ DP (`dp[i]` = LIS ending at `i`) cleanly, then motivates the patience-sorting / `tails` optimization rather than presenting it as magic. - **Optimal complexity**: arrives at $O(n \log n)$ time and $O(n)$ space, and justifies why $O(n^2)$ fails the $2 \times 10^5$ bound. - **Strictness handled precisely**: uses a lower-bound (`>= x`) search and can explain why upper-bound would compute the non-decreasing variant — and that `tails` is **not** itself a valid subsequence, only a length witness. - **Edge cases**: empty/singleton/all-equal arrays, negatives, large ranges. - **Clean implementation**: correct binary search (no off-by-one), idiomatic use of a standard library bisection (`bisect_left`, `lower_bound`) where available. ### Follow-up Questions - Modify your solution to return the **actual** longest increasing subsequence, not just its length. (Hint: track predecessor indices.) - How would you adapt the algorithm to count **non-decreasing** subsequences instead of strictly increasing ones? - If the array arrives as a stream and you must report the current LIS length after each new element, what is the per-element cost of your approach? - Can you do better than $O(n \log n)$ in any restricted setting (e.g. when values are a permutation of $1..n$, or bounded to a small range)? - How would you parallelize or shard this if `n` were $10^9$ and the data did not fit in memory?

Quick Answer: This question evaluates understanding of subsequences, dynamic programming and algorithmic optimization for array processing, and is categorized under Coding & Algorithms; it emphasizes practical application of algorithm design and complexity analysis rather than purely theoretical knowledge.

You are given an integer array `nums` of length `n`. A **subsequence** of `nums` is a sequence derived from `nums` by deleting zero or more elements without changing the order of the remaining elements; elements need **not** be contiguous. A subsequence is **strictly increasing** if every element is strictly greater than the previous one. **Task:** Return the length of the longest strictly increasing subsequence of `nums`. ### Examples - `nums = [10, 9, 2, 5, 3, 7, 101, 18]` -> `4` (e.g. `[2, 3, 7, 101]`) - `nums = [0, 1, 0, 3, 2, 3]` -> `4` (e.g. `[0, 1, 2, 3]`) - `nums = [7, 7, 7, 7]` -> `1` (equal values do not extend a strictly increasing run) ### Constraints - `1 <= n <= 2 * 10^5` (so an O(n^2) DP is too slow; aim for O(n log n)). - `-10^9 <= nums[i] <= 10^9`. - "Increasing" means **strictly** increasing. - The array is non-empty, so the answer is always at least `1`. - Return only the **length**, not the subsequence itself.

Constraints

  • 1 <= n <= 2 * 10^5
  • -10^9 <= nums[i] <= 10^9
  • Increasing means STRICTLY increasing (equal values do not extend a run)
  • The array is non-empty; the answer is always at least 1
  • Return only the length, not the subsequence itself

Examples

Input: [10, 9, 2, 5, 3, 7, 101, 18]

Expected Output: 4

Explanation: One longest strictly increasing subsequence is [2, 3, 7, 101], length 4.

Input: [0, 1, 0, 3, 2, 3]

Expected Output: 4

Explanation: One longest strictly increasing subsequence is [0, 1, 2, 3], length 4.

Input: [7, 7, 7, 7]

Expected Output: 1

Explanation: All values equal; strict increase requires a real increase, so each element forms its own length-1 run.

Input: [5]

Expected Output: 1

Explanation: A single element is itself a subsequence of length 1.

Input: [5, 4, 3, 2, 1]

Expected Output: 1

Explanation: Strictly decreasing; every element overwrites tails[0], so the best run is length 1.

Input: [1, 2, 3, 4, 5]

Expected Output: 5

Explanation: Strictly increasing; every element appends to tails, giving length 5.

Input: [-1000000000, 0, 1000000000]

Expected Output: 3

Explanation: Full-range values, strictly increasing; answer 3 with no overflow since only comparisons are used.

Input: [4, 10, 4, 3, 8, 9]

Expected Output: 3

Explanation: Longest strictly increasing subsequence is [4, 8, 9] (or [3, 8, 9]), length 3; the duplicate/reset of 4 and 3 keeps tails small.

Hints

  1. There is an O(n^2) DP: dp[i] = length of the LIS ending at index i = 1 + max(dp[j]) over all j < i with nums[j] < nums[i]; the answer is max_i dp[i]. This clarifies the recurrence before optimizing.
  2. For O(n log n), maintain an array `tails` where tails[k] is the smallest tail value of any strictly increasing subsequence of length k+1. `tails` stays sorted, so you can binary-search it.
  3. For each x = nums[i], lower-bound search `tails` for the leftmost index with value >= x. If found, overwrite it with x; if x exceeds every tail, append it. The answer is len(tails). Using >= x (lower bound) enforces STRICT increase; > x (upper bound) would count non-decreasing subsequences instead.
  4. Edge cases: a singleton returns 1; an all-equal array returns 1 because each repeat overwrites tails[0] instead of appending; negatives and the full range need no special handling since you only compare raw integers.
Last updated: Jun 26, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Parse a nested list from a string - TikTok (medium)
  • Implement stacks, streaming median, and upward path sum - TikTok (easy)
  • Implement stack variants and path-sum check - TikTok (medium)
  • Find the longest palindromic substring - TikTok (easy)
  • Maximize sum with no adjacent elements - TikTok (medium)