{x}
blog image

Delete Columns to Make Sorted

You are given an array of n strings strs, all of the same length.

The strings can be arranged such that there is one on each line, making a grid.

  • For example, strs = ["abc", "bce", "cae"] can be arranged as follows:
abc
bce
cae

You want to delete the columns that are not sorted lexicographically. In the above example (0-indexed), columns 0 ('a', 'b', 'c') and 2 ('c', 'e', 'e') are sorted, while column 1 ('b', 'c', 'a') is not, so you would delete column 1.

Return the number of columns that you will delete.

 

Example 1:

Input: strs = ["cba","daf","ghi"]
Output: 1
Explanation: The grid looks as follows:
  cba
  daf
  ghi
Columns 0 and 2 are sorted, but column 1 is not, so you only need to delete 1 column.

Example 2:

Input: strs = ["a","b"]
Output: 0
Explanation: The grid looks as follows:
  a
  b
Column 0 is the only column and is sorted, so you will not delete any columns.

Example 3:

Input: strs = ["zyx","wvu","tsr"]
Output: 3
Explanation: The grid looks as follows:
  zyx
  wvu
  tsr
All 3 columns are not sorted, so you will delete all 3.

 

Constraints:

  • n == strs.length
  • 1 <= n <= 100
  • 1 <= strs[i].length <= 1000
  • strs[i] consists of lowercase English letters.

Solution Explanation: Deleting Columns to Make Sorted

This problem asks to find the minimum number of columns to delete from a string array to make the remaining columns lexicographically sorted. A column is lexicographically sorted if each character in the column is less than or equal to the character below it.

Approach:

The most efficient approach involves iterating through the columns and checking for lexicographical order within each column. We don't need to rearrange the columns; we only need to count how many columns need deleting.

Algorithm:

  1. Initialization:

    • Initialize a deletedColumns counter to 0. This will track the number of columns to be deleted.
    • Get the number of rows (n) and columns (m) from the input array.
  2. Iterate through Columns:

    • Use nested loops to iterate through each column (j) and then each row (i) within that column, starting from the second row (index 1).
  3. Lexicographical Check:

    • Compare the character at strs[i][j] with the character at strs[i-1][j].
    • If strs[i][j] < strs[i-1][j], it means the column is not lexicographically sorted. Increment deletedColumns and break the inner loop (no need to check further down the column).
  4. Return Result:

    • After iterating through all columns, return the value of deletedColumns.

Time and Space Complexity:

  • Time Complexity: O(m*n), where 'm' is the number of columns and 'n' is the number of rows. We iterate through each cell of the matrix once in the worst case.

  • Space Complexity: O(1). The algorithm uses a constant amount of extra space.

Code in Different Languages:

The following code demonstrates the solution in several popular programming languages. Note that minor variations may exist depending on language specifics.

Python:

def minDeletionSize(strs):
    n = len(strs)
    m = len(strs[0]) if n > 0 else 0  # Handle empty input
    deletedColumns = 0
 
    for j in range(m):
        for i in range(1, n):
            if strs[i][j] < strs[i-1][j]:
                deletedColumns += 1
                break  # No need to check further in this column
 
    return deletedColumns

Java:

class Solution {
    public int minDeletionSize(String[] strs) {
        int n = strs.length;
        int m = (n > 0) ? strs[0].length() : 0;
        int deletedColumns = 0;
 
        for (int j = 0; j < m; j++) {
            for (int i = 1; i < n; i++) {
                if (strs[i].charAt(j) < strs[i - 1].charAt(j)) {
                    deletedColumns++;
                    break;
                }
            }
        }
        return deletedColumns;
    }
}

C++:

class Solution {
public:
    int minDeletionSize(vector<string>& strs) {
        int n = strs.size();
        int m = (n > 0) ? strs[0].length() : 0;
        int deletedColumns = 0;
 
        for (int j = 0; j < m; j++) {
            for (int i = 1; i < n; i++) {
                if (strs[i][j] < strs[i - 1][j]) {
                    deletedColumns++;
                    break;
                }
            }
        }
        return deletedColumns;
    }
};

JavaScript:

const minDeletionSize = (strs) => {
    const n = strs.length;
    const m = (n > 0) ? strs[0].length : 0;
    let deletedColumns = 0;
 
    for (let j = 0; j < m; j++) {
        for (let i = 1; i < n; i++) {
            if (strs[i][j] < strs[i - 1][j]) {
                deletedColumns++;
                break;
            }
        }
    }
    return deletedColumns;
};

These code snippets all follow the same algorithm and achieve the same result, providing a clear and efficient solution to the problem. They handle the edge case of an empty input array gracefully.