Python3 avg better than O(MN) - Delete Columns to Make Sorted II
The key is to keep a list ranges in which each element represents a range in which all characters (more than one) are the same in the immediate previous column 
The key is to keep a list `ranges` in which each element represents a range in which all characters (more than one) are the same in the immediate previous column that can be kept. When updating `ranges`, only find ranges within a range of the previous column. As soon as `ranges` is empty, we know all the remaining columns can be kept, so that we can return early.\n\nFor example:\n\naxy\n**ba**e\n**ba**f\n**b**cf\nczz\n**d**ih\n**d**jk\nefg\n\nThe answer for this input is 0.\nAfter column 0, `ranges` contains 2 ranges: the 3 `b`s and 2 `c`s.\nAfter column 1, `ranges` contains 1 range the 2 `a`s whose parent range is the 3 `b`s.\nAfter column 2, `ranges` is empty because the 2 `a`s children are different. There are 2 `f`s, but their parents are not in a range.\nIf there are any more columns, they can all be kept.\n\n```\nclass Solution:\n    def minDeletionSize(self, A: List[str]) -> int:\n        def isSorted(arr, i, j):\n            return all(arr[k] <= arr[k+1] for k in range(i, j))\n        ans = 0\n        ranges = [[0, len(A)-1]]\n        for col in zip(*A):\n            if not ranges:\n                break\n            if all(isSorted(col, i, j) for i, j in ranges):\n                tmp = []\n                for i, j in ranges:\n                    start = i\n                    for k in range(i, j+1):\n                        if col[k] != col[start]:\n                            if k - start > 1:\n                                tmp.append([start, k-1])\n                            start = k   \n                    if j + 1 - start > 1:\n                        tmp.append([start, j])\n                    start = k   \n                ranges[:] = tmp\n            else:    \n                ans += 1\n        return ans\n```
['Python', 'Python3']