P1 重新排列单词间的空格
给你一个字符串 text ,该字符串由若干被空格包围的单词组成。每个单词由一个或者多个小写英文字母组成,并且两个单词之间至少存在一个空格。题目测试用例保证 text 至少包含一个单词 。
请你重新排列空格,使每对相邻单词之间的空格数目都 相等 ,并尽可能 最大化 该数目。如果不能重新平均分配所有空格,请 将多余的空格放置在字符串末尾 ,这也意味着返回的字符串应当与原 text 字符串的长度相等。
返回 重新排列空格后的字符串 。
Solution
class Solution:
def reorderSpaces(self, cl text: str) -> str:
words = []
cur = ""
cnt = 0
for ch in text:
if ch == ' ':
cnt += 1
if cur != "":
words.append(cur)
cur = ""
else:
cur = cur + ch
if cur != "":
words.append(cur)
if len(words) == 1:
return words[0] + ' ' * cnt
k = cnt // (len(words) - 1)
r = cnt - k * (len(words) - 1)
ret = words[0]
for x in words[1:]:
ret += ' '*k + x
ret += ' ' * r
return ret
P2 拆分字符串使唯一子字符串的数目最大
给你一个字符串 s ,请你拆分该字符串,并返回拆分后唯一子字符串的最大数目。
字符串 s 拆分后可以得到若干 非空子字符串 ,这些子字符串连接后应当能够还原为原字符串。但是拆分出来的每个子字符串都必须是 唯一的 。
注意:子字符串 是字符串中的一个连续字符序列。
Solution
- 穷举
class Solution:
def maxUniqueSplit(self, s: str) -> int:
ret = 1
n = len(s)
def bfs(i, vis):
nonlocal ret
if i == n:
ret = max(ret, len(vis))
return
for j in range(i+1, n + 1):
if s[i:j] not in vis:
bfs(j, vis | {s[i:j]})
bfs(0, set([]))
return ret
P3 矩阵的最大非负积
给你一个大小为 rows x cols 的矩阵 grid 。最初,你位于左上角 (0, 0) ,每一步,你可以在矩阵中 向右 或 向下 移动。
在从左上角 (0, 0) 开始到右下角 (rows - 1, cols - 1) 结束的所有路径中,找出具有 最大非负积 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。
返回 最大非负积 对 109 + 7 取余 的结果。如果最大积为负数,则返回 -1 。
注意,取余是在得到最大积之后执行的。
Solution
- 穷举
- 可以优化只保留最大整数和最小负数
class Solution:
def maxProductPath(self, grid: List[List[int]]) -> int:
n, m = len(grid), len(grid[0])
dp = [[set([]) for _ in range(m)] for _ in range(n)]
for i in range(n):
for j in range(m):
if i == 0 and j == 0:
dp[i][j].add(grid[i][j])
continue
if i - 1 >= 0:
for x in dp[i-1][j]:
dp[i][j].add(x * grid[i][j])
if j - 1 >= 0:
for x in dp[i][j - 1]:
dp[i][j].add(x * grid[i][j])
ret = max(dp[-1][-1])
return -1 if ret < 0 else ret % (10 **9 + 7)
P4 连通两组点的最小成本
给你两组点,其中第一组中有 size1 个点,第二组中有 size2 个点,且 size1 >= size2 。
任意两点间的连接成本 cost 由大小为 size1 x size2 矩阵给出,其中 cost[i][j] 是第一组中的点 i 和第二组中的点 j 的连接成本。如果两个组中的每个点都与另一组中的一个或多个点连接,则称这两组点是连通的。换言之,第一组中的每个点必须至少与第二组中的一个点连接,且第二组中的每个点必须至少与第一组中的一个点连接。
返回连通两组点所需的最小成本。
Solution
- 复杂度是 O ( n ∗ m ∗ 3 m ) O(n*m*3^m) O(n∗m∗3m)
- 枚举剩余状态的子集用
v = mask & (v - 1)
class Solution:
def connectTwoGroups(self, cost: List[List[int]]) -> int:
n, m = len(cost), len(cost[0])
cum_cost = [[0] * (1 << m) for _ in range(n)]
for i in range(n):
for state in range(1 << m):
for j in range(m):
if state & (1 << j) > 0:
cum_cost[i][state] += cost[i][j]
inf = 10 ** 18
dp = [[inf] * (1 << m) for _ in range(n)]
dp[0] = cum_cost[0]
for i in range(1, n):
for state in range(1, 1 << m):
for j in range(m):
k = 1 << j
dp[i][state | k] = min(dp[i][state | k], dp[i-1][state] + cum_cost[i][k])
rest = (1 << m) - 1 - state
v = rest
while v > 0:
dp[i][state | v] = min(dp[i][state | v], dp[i-1][state] + cum_cost[i][v])
v = rest & (v - 1)
return dp[-1][-1]