Leetcode Link: 6150. 根据模式串构造最小数字 - 力扣(LeetCode)
题目

解法一
思路: 这题有点难想,我当时做出来的时候是举了很多的例子,并且自己也造了很多的例子。如果在复习的时候也看到了这里,同样需要这样做,为了方便,提前给你几个例子
- “IDDIIIDD”
- “IDIDID”
- “DIIDI”
- “DDDIIIDI”
题目中的关键是”返回字典序最小的结果”,尝试分析上面的例子,我们可以简单得到下面的几个东西
- 返回结果的数字包含所有[1, n+1]的数字,否则字典序一定不是最小的
- 返回的结果长度比输入长度多1位
- 在任意以I结尾的位置,在这之前的结果包含之前的所有数字,比如对于idx = 3的I,此时
res[0:4] contain [1,2,3,4], 不考虑顺序(举例: “IIIII??”或者”DDIIII???”这种) - 在任意 D 位置的时候,我们需要把当前位置之前的最后一个 I 对应的位置到当前位置的所有位置的结果抬升 1,然后在这个位置上是最后一个值减去 1(举例:“IIDDDII”)
大概是这种感觉, 例子 “IIIDDDII”

题解:
class Solution:
def smallestNumber(self, pattern: str) -> str:
res = [1]
# p 为此位置之前最后一个I的位置,初始化为0,可举例
p = 0
i = 0
while(i<len(pattern)):
# 如果遇到D,则需要把p之后到D之前所有位置的结果+1,然后获得此位的结果
if pattern[i] == 'D':
for ii in range(p, len(res)):
res[ii] += 1
res.append(res[-1]-1)
# 如果遇到I,则需要更新p,同时直接获取当前位置的结果
elif pattern[i] == 'I':
res.append(res[p]+1)
p = len(res)-1
# 记得遍历的位置+1
i+=1
ans = [str(val) for val in res]
return ''.join(ans)解法二
思路:一个更为巧妙的解法
我们看上面的例子
大概是这种感觉, 例子 “IIIDDDII”

有点像一个[1:n+1]的数组被部分逆序了!我们只需要考虑在哪里逆序了就行!
举例 pattern = ” I I D D I I” res =“0 1 4 3 2 5 6”
看例子中逆序的那块,其前面最后一个I的idx=1,最后一个D的idx=3。我们res中逆序的部分是位置[2, 4](两边都包含),即两者+1的关系,至此可以写出代码。
题解:
# digits 是python中预定义的变量, = "0123456789"
# 实际上力扣已经帮忙import了
from string import digits
class Solution:
def smallestNumber(self, pattern: str) -> str:
n = len(pattern)
res = list(digits[1:n+2])
i = 0
while(i<len(pattern)):
if pattern[i] == 'I':
i += 1
continue
# 此之前最后的I的位置,可以是-1,下面会加回来
p = i-1
while(i < len(pattern) and pattern[i] == 'D'):
i += 1
# 此时i为最后的D位置+1,因为已经走出了循环。
res[p+1:i+1] = res[p+1:i+1][::-1] # 对应位置逆序
return "".join(res)