1. 程式人生 > >Leetcode 955:刪列造序 ||(超詳細的解法!!!)

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

如有問題,希望大家指出!!!