字符窜

1、1096. 花括号展开 II

考点:

用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))

2、面试题 17.13. 恢复空格

考点:

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]

3、3. 无重复字符的最长子串

考点:

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,其实可以只保留最大的哪个数字即可

 5、166. 分数到小数

1、使用bfs,一层一层的除
2、使用list记录出现过的除数,如果出现,则表示循环,按照题意加“()”
3、注意,除数和被除数可能存在负数这个坑(对于题中说的整数,都要考虑是否为负数
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

6、605. 种花问题

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

7、1594. 矩阵的最大非负积

考点:

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  

8、面试题 10.09. 排序矩阵查找

考点:

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)])

  

posted @ 2020-12-02 10:01  哈哈哈喽喽喽  阅读(103)  评论(0编辑  收藏  举报