【Leetcode】761. Special Binary String 特殊的二进制序列

Special binary strings are binary strings with the following two properties:

The number of 0’s is equal to the number of 1’s.
Every prefix of the binary string has at least as many 1’s as 0’s.
Given a special string S, a move consists of choosing two consecutive, non-empty, special substrings of S, and swapping them. (Two strings are consecutive if the last character of the first string is exactly one index before the first character of the second string.)

At the end of any number of moves, what is the lexicographically largest resulting string possible?

Example 1:

Input: S = “11011000”
Output: “11100100”
Explanation:
The strings “10” [occuring at S[1]] and “1100” [at S[3]] are swapped.
This is the lexicographically largest string possible after some number of swaps.
Note:

  1. S has length at most 50.
  2. S is guaranteed to be a special binary string as defined above.

解法

记录一下这道题,虽然自己做出来了,但是想了好久= =
这个数组条件这么特殊肯定是要利用它的规律然后递归或者DP的
有几条规律有助于我们解题:

  1. 特殊数组一定是1开始0结尾的
  2. 特殊数组的每个1(假设它的下标为i),都能找到一个最小的j(S[j]==0),使得S[i:j+1]是特殊数组:
  • 假设S[:i]中1比0多a个,而i以后一共有b个1,那么S[i:]将会有有a+b>=b个0,不可能0不够,所以j一定存在;
  • 另外由于S[i]是1,所以一开始1就比0多一个,假设存在i<=k<=j使得S[i:k+1]中1比0少,那么必然会经历【1比0多,1等于0,1少于0】的过程,这与j是最小的使得S[i:j+1]是特殊数组的条件矛盾。
  1. 由第二条可以推出,由于S[0]一定等于1,S[0]对应的j:
    • 要么j==len(S),我们把这样的字符串称作最小单元
    • 要么j<len(S),这时S一定由多个最小单元连接而成。【因为S[:j+1]是特殊数组,那么要使S是特殊数组,S[j+1:]也得是特殊数组】
  2. 对于最小单元UU[1:-1]也是特殊数组。

    我们假设U[:i]里有x个1,那么就有i-x个0;所以U[1:i]就有x-1个1和i-x个0。由于U是最小单元,所以一定有x>i-x,不然U[:i]才是最小单元,那么必然有x-1>=i-x,所以U[1:-1]也是特殊数组

现在我们可以得到算法了:

  1. 假设S是最小单元,那么我们能得到的最大字典序显然就是"1"+solve(S[1:-1])+"0"
  2. 假设S由多个最小单元组成,那么对每个最小单元都可以按第一步求出它们的最大字典序。下一步就是把这些单元进行排列,【通过若干次连续交换我们肯定能得到这些单元的任意排列】,怎么排序呢?当然是字典序大的单元排在前面啦!

    这样会不会有问题呢?答案是没有的。
    假如单元们都一样长,那么直接排序肯定是没问题的。
    假如不一样长,一个单元是A,另一个单元是B+C,其中A和B的长度相同。
    如果A!=B,那么直接按排序结果也是没问题的
    如果A==B,嗯?如果A==B那么B也是最小单元,那么根本不可能出现B+C
    综上所述长度不同的单元也完全可以按字典序比较

几个优化:

  1. 记忆化搜索
  2. 如果当前数组已经是字典序最大了,就不用再递归下去啦
class Solution(object):
    def makeLargestSpecial(self, S):
        """
        :type S: str
        :rtype: str
        """
        mem = {}
            
        def solve(s):
            if s not in mem:
                if s.endswith('0'*(len(s)//2)):
                    mem[s] = s
                else:
                    units = []
                    ones = 0
                    b = None
                    for i,c in enumerate(s):
                        if c=='1':
                            if ones == 0:
                                b = i
                            ones += 1
                        else:
                            ones -= 1
                            if ones==0:
                                units.append("1"+solve(s[b+1:i])+"0")
                    mem[s] = "".join(list(sorted(units,reverse=True)))
            return mem[s]
        
        return solve(S)

猜你喜欢

转载自blog.csdn.net/lemonmillie/article/details/86567598