--- comments: true difficulty: 困难 edit_url: https://github.com/doocs/leetcode/edit/main/solution/0900-0999/0960.Delete%20Columns%20to%20Make%20Sorted%20III/README.md tags: - 数组 - 字符串 - 动态规划 --- # [960. 删列造序 III](https://leetcode.cn/problems/delete-columns-to-make-sorted-iii) [English Version](/solution/0900-0999/0960.Delete%20Columns%20to%20Make%20Sorted%20III/README_EN.md) ## 题目描述

给定由 n 个小写字母字符串组成的数组 strs ,其中每个字符串长度相等。

选取一个删除索引序列,对于 strs 中的每个字符串,删除对应每个索引处的字符。

比如,有 strs = ["abcdef","uvwxyz"] ,删除索引序列 {0, 2, 3} ,删除后为 ["bef", "vyz"] 。

假设,我们选择了一组删除索引 answer ,那么在执行删除操作之后,最终得到的数组的行中的 每个元素 都是按字典序排列的(即 (strs[0][0] <= strs[0][1] <= ... <= strs[0][strs[0].length - 1]) 和 (strs[1][0] <= strs[1][1] <= ... <= strs[1][strs[1].length - 1]) ,依此类推)。

请返回 answer.length 的最小可能值 。

 

示例 1:

输入:strs = ["babca","bbazb"]
输出:3
解释:
删除 0、1 和 4 这三列后,最终得到的数组是 strs = ["bc", "az"]。
这两行是分别按字典序排列的(即,strs[0][0] <= strs[0][1] 且 strs[1][0] <= strs[1][1])。
注意,strs[0] > strs[1] —— 数组 strs 不一定是按字典序排列的。

示例 2:

输入:strs = ["edcba"]
输出:4
解释:如果删除的列少于 4 列,则剩下的行都不会按字典序排列。

示例 3:

输入:strs = ["ghi","def","abc"]
输出:0
解释:所有行都已按字典序排列。

 

提示:

## 解法 ### 方法一 #### Python3 ```python class Solution: def minDeletionSize(self, strs: List[str]) -> int: n = len(strs[0]) dp = [1] * n for i in range(1, n): for j in range(i): if all(s[j] <= s[i] for s in strs): dp[i] = max(dp[i], dp[j] + 1) return n - max(dp) ``` #### Java ```java class Solution { public int minDeletionSize(String[] strs) { int n = strs[0].length(); int[] dp = new int[n]; Arrays.fill(dp, 1); int mx = 1; for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { if (check(i, j, strs)) { dp[i] = Math.max(dp[i], dp[j] + 1); } } mx = Math.max(mx, dp[i]); } return n - mx; } private boolean check(int i, int j, String[] strs) { for (String s : strs) { if (s.charAt(i) < s.charAt(j)) { return false; } } return true; } } ``` #### C++ ```cpp class Solution { public: int minDeletionSize(vector& strs) { int n = strs[0].size(); vector dp(n, 1); int mx = 1; for (int i = 1; i < n; ++i) { for (int j = 0; j < i; ++j) { if (check(i, j, strs)) { dp[i] = max(dp[i], dp[j] + 1); } } mx = max(mx, dp[i]); } return n - mx; } bool check(int i, int j, vector& strs) { for (string& s : strs) if (s[i] < s[j]) return false; return true; } }; ``` #### Go ```go func minDeletionSize(strs []string) int { n := len(strs[0]) dp := make([]int, n) mx := 1 dp[0] = 1 check := func(i, j int) bool { for _, s := range strs { if s[i] < s[j] { return false } } return true } for i := 1; i < n; i++ { dp[i] = 1 for j := 0; j < i; j++ { if check(i, j) { dp[i] = max(dp[i], dp[j]+1) } } mx = max(mx, dp[i]) } return n - mx } ```