字符窜
考点:
用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)])