字符窜
考点:
用stack做,维持两个list:
第一个list代表已经计算好的部分,第二个list代表增长中的未知部分
看到字母就“乘入”第二个list,例如[a]*b变成“ab”,[a,c]*b就变成['ab','cb']
看到“,”就代表第二个list已经不可能再继续增长了,把第二个list并入第一个list并清空。
看到“{”就把两个list推入stack
看到“}”就把两个list从stack pop出来并把当前结果“乘入”第二个list。
最终把两个list合并下就是答案。
这种双“计算完”+“计算中”的双list方法稍加变化可以通用到所有带括号的公式计算题中。
如果不考虑返回前的那次sort,时间复杂度为O(n)
class Solution:
def braceExpansionII(self, expression: str) -> List[str]:
stack = []
pre, cur = [], []
for ch in expression:
if 'A' <= ch <= 'z':
cur = [i+ch for i in cur or ['']]
elif "," == ch:
pre = pre + cur
cur = []
elif "{" == ch:
stack.append(pre)
stack.append(cur)
pre = []
cur = []
elif "}" == ch:
cur_be = stack.pop()
pre_be = stack.pop()
cur = [j+i for i in pre + cur for j in cur_be or ['']]
pre = pre_be
return sorted(set(pre + cur))
考点:
1、动态规划
class Solution:
def respace(self, dictionary, sentence) -> int:
select_diction = set()
for diction in dictionary:
try:
sentence.index(diction)
select_diction.add(diction)
except:
continue
len_set = set([len(i) for i in select_diction])
# print(len_set)
sentence_len = len(sentence)
sentence_list = [sentence_len] * (sentence_len+1)
sentence_list[0] = 0
# print(sentence_list)
for i in range(len(sentence_list)):
if not i == 0:
sentence_list[i] = 1 + sentence_list[i-1]
for ilen in len_set:
if i < ilen:
continue
if sentence[i-ilen:i] in select_diction:
sentence_list[i] = \
min(sentence_list[i], sentence_list[i-ilen])
# print(sentence_list)
return sentence_list[-1]
考点:
1、双指针
2、注意,字符窜长度为0和1时,需要单独返回
3、注意,for里面的有指针是len(str) + 1
class Solution:
def lengthOfLongestSubstring(self, s):
if len(s) == 0:
return 0
if len(s) == 1:
return 1
left = 0
result = 0
for right in range(1, len(s)+1):
if len(set(s[left:right])) == right - left:
if right - left > result:
result = right - left
continue
while True:
left = left + 1
if right == left:
break
if not len(set(s[left:right])) == right - left:
continue
else:
break
return result
4、1449. 数位成本和为目标值的最大数字
考点:
1、计算从0 到target最大字符串;只要计算每个位置最大字符串就可以,存在最优子结构,所有使用动态规划
2、注意,max函数需要先比位数,相同位数再比较大小
class Solution:
def largestNumber(self, cost: List[int], target: int) -> str:
cost_nums = collections.defaultdict(list)
for index, i in enumerate(cost):
cost_nums[i].append(index+1)
print(cost_nums)
tmp_list = ["0"] * (target+1)
tmp_list[0] = ""
def imax(str1, str2):
if len(str1) > len(str2):
return str1
elif len(str1) < len(str2):
return str2
else:
return max(str1, str2)
for i in range(len(tmp_list)):
for icost in cost_nums.keys():
if icost > i:
continue
if not tmp_list[i-icost] == "0":
tmp_list[i] = imax(tmp_list[i], tmp_list[i-icost]+str(max(cost_nums[icost])))
if i == icost:
tmp_list[i] = imax(tmp_list[i], str(max(cost_nums[icost])))
# print(tmp_list)
return tmp_list[-1]
以上代码,cost_nums 的value是一个list,其实可以只保留最大的哪个数字即可
class Solution:
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
before_zero = 0
if numerator < 0:
numerator = -1 * numerator
before_zero += 1
if denominator < 0:
denominator = -1 * denominator
before_zero += 1
print(before_zero)
if numerator == 0:
return "0"
global result
result = ""
if numerator < denominator:
result = "0."
numerator = numerator * 10
else:
result = str(int(numerator/denominator))
numerator = numerator % denominator * 10
if numerator == 0:
return result if before_zero %2 == 0 else "-"+result
result = result + "."
history_index = []
def bfs(numerator):
global result
print(numerator, result)
print(numerator, result)
if numerator in history_index:
start = history_index.index(numerator)
result_list = result.split(".")
result = result_list[0] + "." + result_list[1][:start] + "(" + result_list[1][start:] + ")"
return
if numerator < denominator:
result = result + "0"
history_index.append(numerator)
bfs(numerator * 10)
return
# 添加循环,结束
else:
tmp = str(int(numerator/denominator))
result = result + tmp
history_index.append(numerator)
numerator = numerator % denominator
if numerator == 0:
return
else:
bfs(numerator*10)
bfs(numerator)
print(result)
return result if before_zero %2 == 0 else "-"+result
1、需单独考虑最前面和最后面位置
2、此种非算法题,一定要自己写测试用例,全面的测试用例;1位的几种情况,2位的几种情况,然后3位的,前后有00的,这种边界值最容易错
class Solution:
def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
if n == 0:
return True
##### flowerbed长度为1
if len(flowerbed) == 1:
if flowerbed[0] == 0:
return True
else:
return False
##### flowerbed长度为2
if len(flowerbed) == 2:
print(sum(flowerbed))
if sum(flowerbed) > 0:
return False
elif n>1:
return False
return True
#### flowerbed 长度大于3
if flowerbed[0] == 0 and flowerbed[1] == 0:
n = n -1
flowerbed[0] = 1
# print(flowerbed[-1], flowerbed[-2])
if flowerbed[-1] == 0 and flowerbed[-2] == 0:
n = n -1
flowerbed[-1] = 1
# print(n, flowerbed)
for i in range(1, len(flowerbed)-1):
if n == 0:
return True
# print(flowerbed[i], flowerbed[i-1])
if flowerbed[i]==0 and flowerbed[i-1] ==0 and flowerbed[i+1] == 0:
n = n -1
flowerbed[i] = 1
continue
# print(n)
return True if n <= 0 else False
考点:
1、计算每个位置值,每个值有上面值和左边值决定; 所以使用动态规划
2、注意,生成二维矩阵,为 [[set()] * col for i in range(row)], 容易被误写为[[set()] * row for i in range(col)]
class Solution:
def maxProductPath(self, grid: List[List[int]]) -> int:
row = len(grid)
col = len(grid[0])
# print(row, col)
result = [[set()] * col for i in range(row)]
tmp = set()
tmp.add(grid[0][0])
result[0][0] = tmp
# print(result)
for i in range(row):
for j in range(col):
# print("*", str(i) + "$" +str(j))
for ii, jj in [(i-1, j), (i, j-1)]:
# print(ii, jj)
if 0 <= ii < row and 0 <= jj < col:
tmp = [k * grid[i][j] for k in result[ii][jj]]
result[i][j] = result[i][j] | set(tmp)
# print(result)
tmp_result = max(result[row-1][col-1])
return tmp_result%(10 **9 +7) if tmp_result >= 0 else -1
考点:
1、按照常规,从(0, 0)开始,向右向下找,直到找到target,然后就超时了
2、进一步优化,发现正斜线上点有一些特点,在该点以上,以左边 都比该值小; 比该点以下以右均比改值大。因此优化为先找到斜线上第一个比target大的点,然后以该点行列分别为0 进行向右向下找,
然后就 还是超时
3、进一步优化,常规套路,把已经遍历的点加到set中,不重复遍历即可
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
# 1维 []
if not matrix:
return False
# [[]]
if not matrix[0]:
return False
if matrix[0][0] == target:
return True
row = len(matrix)
col = len(matrix[0])
# 按照正斜角比对,找到临近分叉点(因为 斜角以上均比该值小,斜角以下均比该值大)
start = 0
for i in range(min(row, col)):
# print(matrix[i][i], target)
if matrix[i][i] == target:
return True
elif matrix[i][i] > target:
start = i
break
print(i)
visited = set()
def bfs(cur_list):
next_list = []
for cur in cur_list:
i, j = cur
for ii, jj in [(i+1, j), (i, j+1)]:
if (ii, jj) not in visited:
if 0 <= ii < row and 0 <= jj < col:
if matrix[ii][jj] == target:
return True
if matrix[ii][jj] < target:
visited.add((ii, jj))
next_list.append((ii, jj))
if next_list:
return bfs(next_list)
return False
return bfs([(i -1, 0), (0, i -1)])

浙公网安备 33010602011771号