Leetcode 955:删列造序 ||(超详细的解法!!!)

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

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

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

假设,我们选择了一组删除索引 D,那么在执行删除操作之后,最终得到的数组的元素是按 字典序A[0] <= A[1] <= A[2] ... <= A[A.length - 1])排列的,然后请你返回 D.length 的最小可能值。

示例 1:

输入:["ca","bb","ac"]
输出:1
解释: 
删除第一列后,A = ["a", "b", "c"]。
现在 A 中元素是按字典排列的 (即,A[0] <= A[1] <= A[2])。
我们至少需要进行 1 次删除,因为最初 A 不是按字典序排列的,所以答案是 1。

示例 2:

输入:["xc","yb","za"]
输出:0
解释:
A 的列已经是按字典序排列了,所以我们不需要删除任何东西。
注意 A 的行不需要按字典序排列。
也就是说,A[0][0] <= A[0][1] <= ... 不一定成立。

示例 3:

输入:["zyx","wvu","tsr"]
输出:3
解释:
我们必须删掉每一列。

提示:

  1. 1 <= A.length <= 100
  2. 1 <= A[i].length <= 100

解题思路

这是之前问题Leetcode 944:删列造序(超详细的解法!!!)的扩展。这个问题的主要难点在于我们需要考虑这样的情况["xga","xfb","yfa"],此时我们发现x出现两次,那么我们就要比较其后的gf是否满足字典序。我们首先看一个较为朴素的思路

我们首先遍历第一行和第二行元素,比较他们的第一列元素。我们发现此时它们相同,我们就要接着比较第二列元素。

我们发现对于第二列的元素,第一行的g比第二行的f大,所以我们要删除这一列,我们将其记录到一个set中。接着我们继续看第三列元素。

我们发现第三列元素符合字典序,所我们第一轮遍历结束。我们接着看第二行和第三行。

我们发现此时已经满足字典序,并且第二行元素比第三行小,所以我们可以不用再向后比较了。我们最后只要返回我们记录的set的大小即可。

class Solution:
    def minDeletionSize(self, A):
        """
        :type A: List[str]
        :rtype: int
        """
        d = set()
        row, col = len(A), len(A[0])
        i = 1
        while i < row:
            for j in range(col):
                if j in d or A[i-1][j] == A[i][j]:
                    continue
                if A[i-1][j] > A[i][j]:
                    d.add(j)
                    i = 0
                    
                break
            i += 1
                
        return len(d)

我们还有一个更好的思路,通过记录之前列的排序状态。我们首先将状态初始化为False

我们首先看第一列的元素

我们发现已经全部按照字典序排列了,所以我们接着看第二列,并且我们需要记录第一列的排序状态。x==x,我们也将其记录为False(因为我们要考虑后续列的状态),接着x<y,所以我们要记录为True

我们发现第二列的第一行和第二行元素不满足字典序,所以我们要删除这一列,不用再检查后面行的元素了。我们接着看第三列

我们首先看前两个元素,我们发现排好序了,所以我们接着看后两个元素。

我们发现后两个元素没有排好序,所以这个时候我们要看前面一个没有删除的列的情况(这里就是第一列),来考虑当前列要不要删除。我们可以从type中知道前面是True,也就是说前面一列当前行的位置已经排好序了,所以我们当前列也不用删除。此时我们要更新排序状态。

class Solution:
    def minDeletionSize(self, A):
        """
        :type A: List[str]
        :rtype: int
        """
        row, col = len(A), len(A[0])
        res = 0
        s = [False]*(row - 1)
        for j in range(col):
            i = 0
            while i < row - 1:
                if not s[i] and A[i][j] > A[i + 1][j]:
                    res += 1
                    break
                i += 1
                    
            if i < row - 1:
                continue
                
            i = 0
            while i < row - 1:
                if A[i][j] < A[i + 1][j]:
                    s[i] = True
                    
                i += 1
                    
        return res

reference:

https://leetcode.com/problems/delete-columns-to-make-sorted-ii/discuss/203182/JavaC++Python-Greedy-Solution-O(MN)

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值