Leetcode 960. Delete Columns to Make Sorted III
Given n equal-length strings, delete the fewest column indices so that in every row the remaining characters are non-decreasing. This is equivalent to finding the longest sequence of column indices that is non-decreasing for every row (an LIS-like constraint across columns), and returning m minus that length.
DESCRIPTION
Given n equal-length strings, delete the fewest column indices so that in every row the remaining characters are non-decreasing. This is equivalent to finding the longest sequence of column indices that is non-decreasing for every row (an LIS-like constraint across columns), and returning m minus that length.
Input:
strs = ['abc', 'bce', 'cae']
Output:
1
Explanation: We can keep columns 0 and 2, giving rows 'ac', 'be', 'ce' (all sorted). We delete 1 column (column 1).
Constraints:
- 1 <= strs.length <= 100
- 1 <= strs[i].length <= 100
- All strings have the same length
- Strings consist of lowercase English letters
Understanding the Problem
Let's understand what we're being asked to do. We have n strings of equal length, like ['abc', 'bce', 'cae']. Each string is a row, and we can think of columns as vertical slices: column 0 is 'a', 'b', 'c', column 1 is 'b', 'c', 'a', column 2 is 'c', 'e', 'e'.
We need to delete the minimum number of columns so that in every remaining row, the characters are in non-decreasing order (sorted). For example, if we keep columns 0 and 2, row 0 becomes 'ac' (sorted ✓), row 1 becomes 'be' (sorted ✓), row 2 becomes 'ce' (sorted ✓).
Key constraint: We must ensure ALL rows are sorted after deletion. If even one row is unsorted, that column set doesn't work.
Edge cases to consider: What if all columns must be deleted? What if no columns need deletion (already sorted)? What if n=1 (single string - any column subset works)?
Brute Force Approach
The brute force approach would enumerate all possible subsets of columns (there are 2^m subsets where m is the number of columns). For each subset, check if keeping those columns makes every row sorted. Track the maximum size of a valid subset found. This approach is simple to understand but exponential in time complexity, making it impractical for even moderate input sizes.
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(2^m * n * m) We check 2^m possible column subsets, and for each subset we verify n rows with up to m characters each
Space Complexity: O(m) We only need space to store the current subset being checked
Building Intuition
This problem is asking us to find the longest sequence of column indices such that keeping those columns makes every row sorted.
If we can find the longest valid sequence of length L, then we need to delete m - L columns (where m is the total number of columns). The key insight is that a valid sequence of columns must be non-decreasing in every row simultaneously.
Instead of trying all possible column subsets (which would be exponential), we can use dynamic programming to build up valid sequences incrementally.
For each column, we ask: 'Can I extend any previous valid sequence by adding this column?' This transforms an exponential search into a polynomial-time solution by reusing previously computed results.
Think of this like building a chain of columns. You start with individual columns (chains of length 1). Then you try to extend each chain by adding a new column - but you can only add column j to a chain ending at column i if:
- Column j comes after column i (index-wise)
- For every row, the character in column j is >= the character in column i
This 'building longer chains from shorter ones' pattern is the essence of dynamic programming on sequences.
Common Mistakes
Trying to solve this greedily by deleting columns one at a time - this doesn't guarantee the optimal solution because the order of deletions matters
Forgetting to check ALL rows when comparing two columns - if even one row violates the ordering, those columns cannot be in the same sequence
Confusing this with standard LIS - here we're finding the longest subsequence of column INDICES, not the longest increasing subsequence of characters
Not initializing dp[j] = 1 for all columns - every column by itself forms a valid sequence of length 1
Off-by-one errors when comparing columns - make sure j > i (not j >= i) to avoid comparing a column with itself
Optimal Solution
The optimal approach uses dynamic programming similar to the Longest Increasing Subsequence (LIS) problem. For each column j, we compute dp[j] = the length of the longest valid column sequence ending at column j. We can extend a sequence ending at column i to column j if j > i and for every row, strs[row][j] >= strs[row][i]. The answer is m - max(dp), where max(dp) is the longest valid sequence we can keep.
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(m^2 * n) We have m columns, and for each column we check all previous columns (m comparisons), and each comparison checks n rows
Space Complexity: O(m) We maintain a dp array of size m to store the longest sequence ending at each column
What We've Learned
- Dynamic Programming on column indices: This problem transforms a 2D constraint (all rows must be non-decreasing) into a 1D DP problem by treating columns as elements - use DP[i] to represent the longest valid sequence ending at column i, where validity means all rows satisfy the non-decreasing property between selected columns.
- Longest Increasing Subsequence (LIS) variant recognition: When asked to delete minimum elements to satisfy an ordering constraint, reframe it as finding the maximum elements you can keep - this converts 'minimum deletions' to 'maximum valid subsequence length' where answer = total - max_kept.
- Multi-row validation pattern: For each potential column pair (j, i), you must validate the constraint across ALL rows simultaneously - use a helper function that checks if column j can precede column i by iterating through every row and ensuring s[row][j] <= s[row][i] for all rows.
- Quadratic DP transition optimization: The O(m²) column comparison is unavoidable when each column depends on all previous columns, but optimize by breaking early in validation loops - if any single row violates the non-decreasing property between two columns, immediately return false without checking remaining rows.
- Column-wise thinking for string arrays: When dealing with arrays of equal-length strings where operations affect entire columns, mentally transpose the problem - think of columns as independent units and rows as constraints that must all be satisfied, rather than processing strings individually.
- Greedy won't work insight: You cannot greedily select columns left-to-right because a locally valid choice might block better global solutions - DP is necessary because the optimal subsequence of columns requires considering all possible previous columns at each step, similar to classic LIS where order matters but selection is flexible.
Related Concepts and Problems to Practice
This problem is directly related as it involves finding the longest increasing subsequence using dynamic programming, which is the core technique needed for Delete Columns to Make Sorted III. Both problems require finding the longest valid sequence with ordering constraints.
This problem also uses dynamic programming to find optimal subsequences with constraints. Like the column deletion problem, it requires tracking which elements to include/exclude to maximize a result while maintaining ordering properties.
This lesson provides foundational understanding of how to approach DP problems systematically, which is essential for tackling the column deletion problem that requires identifying optimal substructure and building solutions incrementally.
Test Your Understanding
Why is array the right data structure for this problem?
Select an answer to see the explanation
Question Timeline
See when this question was last asked and where, including any notes left by other candidates.
Hello Interview Premium
Your account is free and you can post anonymously if you choose.