|
| 1 | +# [Problem 955: Delete Columns to Make Sorted II](https://leetcode.com/problems/delete-columns-to-make-sorted-ii/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +I need to delete as few columns as possible so that the remaining rows (strings) are in non-decreasing lexicographic order. Columns can be removed in any set, but deletions affect all rows. A brute-force try-all-subsets of columns is impossible (2^m). A greedy approach scanning columns left-to-right feels natural because lexicographic order compares from left to right: the first differing column determines order between two rows. |
| 5 | + |
| 6 | +So iterate columns from left to right and decide whether to keep or delete each column. If keeping a column would create a violation (some row i > row i+1 considering seen columns so far), then we must delete that column. If keeping it doesn't violate order, we can use it to finalize some row-pair ordering (if character at column makes row i < row i+1 strictly, that pair is permanently ordered and subsequent columns don't need to check that pair). Maintain an array of "confirmed" pairs between consecutive rows. |
| 7 | + |
| 8 | +This is a known greedy solution: for each column, check pairs that are not yet confirmed; if any pair has char_a > char_b at this column, delete the entire column (count +1) and don't update confirmed pairs; otherwise update confirmed pairs where char_a < char_b. Stop early if all pairs become confirmed. |
| 9 | + |
| 10 | +## Refining the problem, round 2 thoughts |
| 11 | +Edge cases: |
| 12 | +- n == 1 -> already sorted, answer = 0. |
| 13 | +- Strings of length 1 or all columns decreasing -> may need to delete all columns. |
| 14 | +- We must ensure when a column is deleted we do not change confirmed pairs; we simply skip the column. |
| 15 | +- Complexity: we check each column and for each column we may inspect up to n-1 pairs, so O(n*m) time and O(n) extra space for the flags. This fits constraints (n, m <= 100). |
| 16 | + |
| 17 | +Alternative: dynamic programming or building minimal set of columns to keep, but greedy is simpler and optimal because lexicographic comparison is left-to-right—the earliest difference matters—so once a pair is confirmed in order, later columns cannot undo it. |
| 18 | + |
| 19 | +## Attempted solution(s) |
| 20 | +```python |
| 21 | +class Solution: |
| 22 | + def minDeletionSize(self, strs: list[str]) -> int: |
| 23 | + if not strs: |
| 24 | + return 0 |
| 25 | + n = len(strs) |
| 26 | + m = len(strs[0]) |
| 27 | + # If only one string, already sorted |
| 28 | + if n <= 1: |
| 29 | + return 0 |
| 30 | + |
| 31 | + # confirmed[i] means strs[i] <= strs[i+1] is already guaranteed by kept columns |
| 32 | + confirmed = [False] * (n - 1) |
| 33 | + deletions = 0 |
| 34 | + |
| 35 | + for col in range(m): |
| 36 | + # Check if keeping this column would cause any violation |
| 37 | + bad = False |
| 38 | + for i in range(n - 1): |
| 39 | + if not confirmed[i] and strs[i][col] > strs[i + 1][col]: |
| 40 | + bad = True |
| 41 | + break |
| 42 | + if bad: |
| 43 | + deletions += 1 |
| 44 | + # delete this column, don't update confirmed, move to next column |
| 45 | + continue |
| 46 | + |
| 47 | + # No violation: update confirmed pairs where this column strictly orders them |
| 48 | + all_confirmed = True |
| 49 | + for i in range(n - 1): |
| 50 | + if not confirmed[i]: |
| 51 | + if strs[i][col] < strs[i + 1][col]: |
| 52 | + confirmed[i] = True |
| 53 | + else: |
| 54 | + # still not confirmed; keep checking others |
| 55 | + all_confirmed = False |
| 56 | + if all_confirmed: |
| 57 | + # all pairs are confirmed, we can stop early |
| 58 | + break |
| 59 | + |
| 60 | + return deletions |
| 61 | +``` |
| 62 | +- Notes about the approach: |
| 63 | + - Greedy left-to-right scanning of columns. If any unconfirmed adjacent pair would be out of order by keeping the column, delete that column. |
| 64 | + - If the column does not cause any violation, use it to mark pairs that become strictly ordered (strs[i][col] < strs[i+1][col]) as confirmed. |
| 65 | + - Early exit when all adjacent pairs are confirmed. |
| 66 | +- Complexity: |
| 67 | + - Time: O(n * m) where n = number of strings and m = length of each string (we inspect each column and up to n-1 adjacent pairs). |
| 68 | + - Space: O(n) extra for the confirmed flags (or O(1) additional beyond input if you reuse input memory, but we use a small boolean array). |
0 commit comments