8.8 ~ 8.14 尽量坚持刷力扣的每日一题,锻炼大脑思维。更新中~~
761. 特殊的二进制序列【递归分治】
题目描述
思路
题目要求0和1的数量相同,我们可以看成()括号匹配,意思就是让括号有效匹配的情况下,尽量让大量的左括号在前面。并且第一个字符一定是1,最后一个字符一定是0,其实证明也好证明,如果第一个数字为0,则以第一个数字为前缀,就不满足题目中的第二个条件,如果最后一个字符是1,则前n- 1的前缀则也不满足第二个条件。我们可以剔除1和0的情况,继续进行分治讨论,知道s的长度小于等于2的情况,只有两种情况,就是10以及空字符串,直接返回即可。递归返回后,将所有特殊字符按降序返回。
AC代码
class Solution:
def makeLargestSpecial(self, ss: str) -> str:
# 内置函数
def dfs(s):
if len(s) <= 2:
return s
cnt, left = 0, 0
subs = list()
for i, ch in enumerate(s):
if ch == '1':
cnt += 1
else:
cnt -= 1
# 找到一组特殊序列
if cnt == 0:
subs.append("1" + dfs(s[left + 1:i]) + "0")
left = i + 1
subs.sort(reverse=True)
return "".join(subs)
return dfs(ss)
1413. 逐步求和得到正数的最小值【思维题】
题目描述
思路
变量数组,找最小前缀和,如果大于等于0,则都是大于等于0的数,则只需要输出1即可,如果小于0,则输出相反数+1
AC代码
class Solution:
def minStartValue(self, nums: List[int]) -> int:
tmp, s = 1, 0
for num in nums:
s += num
tmp = min(tmp, s)
if tmp >= 0:
return 1
else:
return -tmp + 1
640. 求解方程【模拟】
题目描述
思路
将右边全部项移到左边,统计x系数和常量值,得到kx + val = 0, kx = -val. 分三类情况:
- 1.有解,k不为0,最后输出,x = -val/k
- 2.无解,k = 0,val不为0,最后输出“No solution”
- 3.有无穷解, k = val = 0,最后输出“Infinite solution”
思路,用sign1作为等号左边项还是右边项的标记,sign2作为±号的标记。初始sign1 = 1,遇到等号sign1变为-1,sign2的正负与解析到正负有关。num记录单项常数(这里包括x项的常数),valid标识number是否有效,比如x = x就没有效。
AC代码
class Solution:
def solveEquation(self, equation: str) -> str:
k = val = i = 0
n, sign1= len(equation), 1
while i < n:
if equation[i] == '=':
i += 1
sign1 = -1
continue
sign2 = sign1
if equation[i] == '+':
i += 1
elif equation[i] == '-':
i += 1
sign2 = -sign2
num, valid = 0, False
while i < n and equation[i].isdigit():
valid = True
num = num * 10 + int(equation[i])
i += 1
if i < n and equation[i] == 'x':
k += sign2 * num if valid else sign2
i += 1
else:
val += sign2 * num
if k == 0:
return "Infinite solutions" if val == 0 else "No solution"
return "x={}".format(-val//k)
1417. 重新格式化字符串【思维】
题目描述
思路
分别将数字和字符分成两个数组,然后交叉组合。
AC代码
class Solution:
def reformat(self, s: str) -> str:
tmp1 = tmp2 = ""
for ch in s:
if '0' <= ch <= '9':
tmp1 += ch
else:
tmp2 += ch
if abs(len(tmp1) - len(tmp2)) >= 2:
return ""
if len(tmp1) < len(tmp2):
tmp1, tmp2 = tmp2, tmp1
ans = ""
for i in range(len(tmp2)):
ans += tmp1[i] + tmp2[i]
if len(tmp1) != len(tmp2):
ans += tmp1[len(tmp2)]
return ans
1282. 用户分组【哈希】
题目描述
思路
用哈希表存储每个值对应的下标,之后在值中找该值大小的下标个数压入列表
AC代码
class Solution:
def groupThePeople(self, groupSizes: List[int]) -> List[List[int]]:
groups = defaultdict(list) # defaultdict函数,当遇到空的键时,有默认值
for i, size in enumerate(groupSizes): # enumerate函数可以获得下标和对应值
groups[size].append(i)
ans = []
for size, people in groups.items(): # items函数能获得字典的键值对
ans.extend(people[i : i + size] for i in range(0, len(people), size))
return ans
768. 最多能完成排序的块 II【单调栈】
题目描述
思路
通过题目示例我们可以发现,每一个分组的最大值,都是右边大于左边,因此可以用单调栈来维护每个分组的最大值。
- 如果当前值大于等于最右边的分组最大值,则会产生新的一个分组。
- 如果小于,则需要向左边走,直到大于等于某个分组的最大值停止,然后将后面的分组和当前分组融合成一个分组,用最后一个分组的最大值表示。
- 每个分组只需要存最大值
AC代码
class Solution:
def maxChunksToSorted(self, arr: List[int]) -> int:
# 运用单调栈的思想
stack = []
for a in arr:
# 如果栈为空或最后一个分组的最大数小于等于a,则产生新的分组
if len(stack) == 0 or a >= stack[-1]:
stack.append(a)
else:
# 否则,将从右往左找适当的分组加入,且后面的分组和当前的分组融合成一个分组,且把最大值更新
mx = stack.pop()
while stack and a < stack[-1]:
stack.pop()
stack.append(mx)
return len(stack)
1422. 分割字符串的最大得分
题目描述
思路
- 统计0的前缀和,以及1的后缀和(可用num1-前缀和来算)
- 将0的前缀和与1的后缀和相加,就是答案
- 注意:必须是两个非空数组,所以下标不能到n-1,不然第二个就是空数组
AC代码
class Solution:
def maxScore(self, s: str) -> int:
n = len(s)
arr_0 = [0] * n
arr_1 = [0] * n
num_0 = num_1 = 0
for i,ch in enumerate(s):
if ch == '0':
num_0 += 1
else:
num_1 += 1
arr_0[i] = num_0
arr_1[i] = num_1
ans = 0
for i in range(n - 1):
ans = max(ans, arr_0[i] + num_1 - arr_1[i])
return ans
一行代码搞定
return max(s[:i].count('0') + s[i:].count('1') for i in range(1, len(s)))