You are given an array of n strings strs, all of the same length.
We may choose any deletion indices, and we delete all the characters in those indices for each string.
For example, if we have strs = ["abcdef","uvwxyz"] and deletion indices {0, 2, 3}, then the final array after deletions is ["bef", "vyz"].
Suppose we chose a set of deletion indices answer such that after deletions, the final array has every string (row) in lexicographic order. (i.e., (strs[0][0] <= strs[0][1] <= ... <= strs[0][strs[0].length - 1]), and (strs[1][0] <= strs[1][1] <= ... <= strs[1][strs[1].length - 1]), and so on). Return the minimum possible value ofanswer.length.
Input: strs =["babca","bbazb"]Output: 3Explanation: After deleting columns 0,1, and 4, the final array is strs =["bc","az"].Both these rows are individually in lexicographic order(ie. strs[0][0]<= strs[0][1] and strs[1][0]<= strs[1][1]).Note that strs[0]> strs[1]- the array strs is not necessarily in lexicographic order.
The problem is to delete the minimum number of columns so that each row is lexicographically sorted. Instead of thinking about which columns to delete, we can think about which columns to keep. We want to keep the largest set of columns (in order) such that, for every row, the sequence of characters in those columns is non-decreasing. This is similar to finding the longest non-decreasing subsequence (LNDS) of columns across all rows.
Let m be the number of strings and n be the length of each string.
Use DP: dp[j] is the length of the longest valid subsequence ending at column j.
For each column j, check all previous columns i < j. For all rows, if strs[row][i] <= strs[row][j], then column j can follow column i in the subsequence.
Update dp[j] = max(dp[j], dp[i] + 1) if the above condition holds for all rows.
The answer is n - max(dp), i.e., the minimum columns to delete.
classSolution {
public:int minDeletionSize(vector<string>& strs) {
int m = strs.size(), n = strs[0].size();
vector<int> dp(n, 1);
int ans = n -1;
for (int j =0; j < n; ++j) {
for (int i =0; i < j; ++i) {
bool valid = true;
for (int k =0; k < m; ++k) {
if (strs[k][i] > strs[k][j]) {
valid = false;
break;
}
}
if (valid) dp[j] = max(dp[j], dp[i] +1);
}
ans = min(ans, n - dp[j]);
}
return ans;
}
};
classSolution {
publicintminDeletionSize(String[] strs) {
int m = strs.length, n = strs[0].length();
int[] dp =newint[n];
Arrays.fill(dp, 1);
int ans = n - 1;
for (int j = 0; j < n; ++j) {
for (int i = 0; i < j; ++i) {
boolean valid =true;
for (int k = 0; k < m; ++k) {
if (strs[k].charAt(i) > strs[k].charAt(j)) {
valid =false;
break;
}
}
if (valid) dp[j]= Math.max(dp[j], dp[i]+ 1);
}
ans = Math.min(ans, n - dp[j]);
}
return ans;
}
}
classSolution {
funminDeletionSize(strs: Array<String>): Int {
val m = strs.size
val n = strs[0].length
val dp = IntArray(n) { 1 }
var ans = n - 1for (j in0 until n) {
for (i in0 until j) {
var valid = truefor (k in0 until m) {
if (strs[k][i] > strs[k][j]) {
valid = falsebreak }
}
if (valid) dp[j] = maxOf(dp[j], dp[i] + 1)
}
ans = minOf(ans, n - dp[j])
}
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
classSolution:
defminDeletionSize(self, strs: list[str]) -> int:
m, n = len(strs), len(strs[0])
dp: list[int] = [1] * n
ans: int = n -1for j in range(n):
for i in range(j):
if all(strs[k][i] <= strs[k][j] for k in range(m)):
dp[j] = max(dp[j], dp[i] +1)
ans = min(ans, n - dp[j])
return ans
impl Solution {
pubfnmin_deletion_size(strs: Vec<String>) -> i32 {
let m = strs.len();
let n = strs[0].len();
let strs: Vec<Vec<u8>>= strs.iter().map(|s| s.as_bytes().to_vec()).collect();
letmut dp =vec![1; n];
letmut ans = n asi32-1;
for j in0..n {
for i in0..j {
letmut valid =true;
for k in0..m {
if strs[k][i] > strs[k][j] {
valid =false;
break;
}
}
if valid {
dp[j] = dp[j].max(dp[i] +1);
}
}
ans = ans.min(n asi32- dp[j]);
}
ans
}
}