leetcode 存在“尽管 submission 通过了,但解法是错误的”的情况

https://leetcode.com/problems/ones-and-zeroes

这样做贼 jb 快,但却是错的:


https://leetcode.com/problems/ones-and-zeroes/solutions/3924490/accepted-greedy-solution-with-counterexample/


class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        d = []
        for s in strs:
            cnts = [0,0]
            for char in s:
                if char == '0': 
                    cnts[0] +=1
                else:
                    cnts[1] += 1
            if cnts[0] <= m and cnts[1] <= n:
                d.append(cnts)
        sorted_d3 = sorted(d, key=lambda x:(x[0]+x[1], x[0], x[1]))
        m_left, n_left = m, n
        ans3 = 0
        while sorted_d3:
            subset = sorted_d3.pop(0)
            if m_left-subset[0] >= 0 and n_left-subset[1] >= 0:
                ans3 += 1
                m_left = m_left-subset[0]
                n_left = n_left-subset[1]
        sorted_d4 = sorted(d, key=lambda x:(x[0]+x[1], x[1], x[0]))
        m_left, n_left = m, n
        ans4 = 0
        while sorted_d4:
            subset = sorted_d4.pop(0)
            if m_left-subset[0] >= 0 and n_left-subset[1] >= 0:
                ans4 += 1
                m_left = m_left-subset[0]
                n_left = n_left-subset[1]
        m_left, n_left = m, n
        sorted_d1 = sorted(d, key=lambda x:(x[0], x[1]))
        ans1 = 0
        while sorted_d1:
            subset = sorted_d1.pop(0)
            if m_left-subset[0] >= 0 and n_left-subset[1] >= 0:
                ans1 += 1
                m_left = m_left-subset[0]
                n_left = n_left-subset[1]
        m_left, n_left =  m, n
        sorted_d2 = sorted(d, key=lambda x:(x[1], x[0]))
        ans2 = 0
        while sorted_d2:
            subset = sorted_d2.pop(0)
            if m_left-subset[0] >= 0 and n_left-subset[1] >= 0:
                ans2 += 1
                m_left = m_left-subset[0]
                n_left = n_left-subset[1]
        return max(ans1, ans2, ans3, ans4)

我写的应该正确的时间空间比较垃圾的 DP:

Screenshot_20240812_134537

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        from collections import Counter
        dp2 = [[0] * (m + 1) for _ in range(n + 1)]
        counter = [Counter(s) for s in strs]
        for c in counter:
            num_zeros, num_ones = c.get('0', 0), c.get('1', 0)
            for i_zeros in range(m, num_zeros - 1, -1):
                for i_ones in range(n, num_ones - 1, -1):
                    dp2[i_ones][i_zeros] = max(dp2[i_ones][i_zeros], dp2[i_ones - num_ones][i_zeros - num_zeros] + 1)
        return dp2[n][m]

看别人提交的有更快的 DP:
Screenshot_20240812_134710

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        count = []
        for i in strs:
            d_temp = {'0': 0, "1": 0}
            for j in i: d_temp[j]+=1
            count.append((d_temp['0'], d_temp['1']))
        list_0 = sorted(list(set([i[0] for i in count])))
        d_temp = {}
        for i in range(len(list_0)): d_temp[list_0[i]] = i
        new = [[] for i in list_0] 
        for i in count: new[d_temp[i[0]]].append(i)
        for i in new: i.sort(key = lambda x: x[1])
        def dp(loc, m, n):
            if loc == 0:
                start, cnt = 0, 0
                while (m>=0 and n>=0) and start<len(new[loc]):
                    curr_m, curr_n = new[loc][start]
                    m = m-curr_m
                    n = n-curr_n
                    if m>=0 and n>=0: cnt+=1
                    start+=1
                return cnt
            start, cnt, res = 0, 0, [0]*(len(new[loc])+1)
            res[0] = dp(loc-1, m, n)
            while (m>=0 and n>=0) and start<len(new[loc]):
                curr_m, curr_n = new[loc][start]
                m = m-curr_m
                n = n-curr_n
                if m>=0 and n>=0: 
                    cnt+=1
                    res[cnt] = dp(loc-1, m, n)+cnt
                start+=1
            return max(res)
        return dp(len(list_0)-1, m, n)