|
| 1 | +# [Problem 960: Delete Columns to Make Sorted III](https://leetcode.com/problems/delete-columns-to-make-sorted-iii/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +We are allowed to delete some columns (same indices across all rows) so that each resulting row (string) is non-decreasing (characters left-to-right do not decrease). We want to minimize number of deleted columns. |
| 5 | + |
| 6 | +Thinking: Equivalent to keep as many columns as possible such that for each row, the kept columns form a non-decreasing sequence. If we think of columns indices 0..m-1, we need to select a subsequence of columns (in increasing index order) where for every adjacent chosen columns i < j we have for every row r: strs[r][i] <= strs[r][j]. That is a "compatible" relation between columns. So the problem reduces to finding the longest subsequence of columns that is pairwise compatible in the left-to-right order. That is a longest non-decreasing subsequence in a partial order defined by the per-row comparisons. |
| 7 | + |
| 8 | +A direct DP: dp[j] = length of longest valid subsequence ending at column j. For each j, check all i < j and if column i <= column j for all rows then dp[j] = max(dp[j], dp[i] + 1). The answer is m - max(dp). Complexity: O(m^2 * n) checks, which with m,n ≤ 100 is fine. |
| 9 | + |
| 10 | +## Refining the problem, round 2 thoughts |
| 11 | +Edge cases: |
| 12 | +- Single column (m = 1): no deletions needed if single character is trivially non-decreasing in each row -> answer 0. |
| 13 | +- Single row: problem reduces to deleting columns to make the single string non-decreasing — same DP still works because comparisons are over one row. |
| 14 | +- Many rows: need to ensure the pairwise column check verifies all rows. |
| 15 | + |
| 16 | +Optimization thoughts: |
| 17 | +- We can early-break when a row violates s[row][i] <= s[row][j]. |
| 18 | +- Optionally precompute a boolean matrix ok[i][j] indicating compatibility to avoid repeating checks, but with constraints it's unnecessary. |
| 19 | +- Space O(m) for dp; time O(m^2 * n), worst-case 1e6 character comparisons, which is acceptable. |
| 20 | + |
| 21 | +Correctness: |
| 22 | +- The DP enumerates all subsequences in order because dp[j] considers extending any valid subsequence ending before j that is compatible. This yields longest compatible subsequence (classic DP for LIS in O(m^2) with custom comparator). |
| 23 | + |
| 24 | +## Attempted solution(s) |
| 25 | +```python |
| 26 | +from typing import List |
| 27 | + |
| 28 | +class Solution: |
| 29 | + def minDeletionSize(self, strs: List[str]) -> int: |
| 30 | + if not strs: |
| 31 | + return 0 |
| 32 | + n = len(strs) |
| 33 | + m = len(strs[0]) |
| 34 | + # dp[j] = length of longest compatible subsequence of columns ending at j |
| 35 | + dp = [1] * m |
| 36 | + best = 1 |
| 37 | + for j in range(m): |
| 38 | + for i in range(j): |
| 39 | + # check if column i can precede column j (for all rows s[row][i] <= s[row][j]) |
| 40 | + ok = True |
| 41 | + for r in range(n): |
| 42 | + if strs[r][i] > strs[r][j]: |
| 43 | + ok = False |
| 44 | + break |
| 45 | + if ok: |
| 46 | + dp[j] = max(dp[j], dp[i] + 1) |
| 47 | + if dp[j] > best: |
| 48 | + best = dp[j] |
| 49 | + # minimum deletions = total columns - length of longest kept subsequence |
| 50 | + return m - best |
| 51 | +``` |
| 52 | +- Notes: |
| 53 | + - Approach: DP for longest subsequence of compatible columns. For columns i < j, column j can extend column i if for every row r, strs[r][i] <= strs[r][j]. |
| 54 | + - Time complexity: O(m^2 * n) where m = number of columns, n = number of rows. With constraints (<=100), this is efficient. |
| 55 | + - Space complexity: O(m) for dp. |
| 56 | + - Implementation details: early break on row violation to avoid unnecessary checks. The result is m - max(dp). |
0 commit comments