DFS-困难

1  124. 二叉树中的最大路径和 https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/

考点:

1、后续遍历,根据左右节点和当前节点的值,判断当前节点最大路径的值

2、一个需要注意点是,左右节点+当前节点作为步骤1之外一个单独的路径(红色字体部分代码)

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def set_val(self, value):
        if value > self.max_num:
            self.max_num = value

    def helper(self, root):
        if root == None:
            return None

        left_max = self.helper(root.left)
        right_max = self.helper(root.right)
        # 叶子节点
        if left_max == None and right_max == None:
            self.set_val(root.val)
            return root.val
        elif left_max == None:
            value = max(right_max + root.val, root.val)
            self.set_val(value)
            return value
        elif right_max == None:
            value = max(left_max + root.val, root.val)
            self.set_val(value)
            return value
        else:
            value = max(left_max + root.val, right_max + root.val, root.val)
            value2 = left_max + right_max + root.val
            if value > value2:
                self.set_val(value)
            else:
                self.set_val(value2)
            return value

    def maxPathSum(self, root: TreeNode) -> int:
        # 后序遍历, 则当前节点最大路径为 max(左右+当前节点, 左+当前节点,右+当前节点, 当前节点)
        self.max_num = root.val
        self.helper(root)
        return self.max_num

980. 不同路径 III https://leetcode-cn.com/problems/unique-paths-iii/

考点:

1、深度搜索,碰到非-1值迭代搜索路径; 结束条件为 碰到结束点,满足条件是走过了全路径,即走过路径长度等于全路径长度

class Solution:
    def helper(self, grid, cur, cur_path):
        print(cur, self.end)
        if cur == self.end:
            if len(cur_path) == self.path_len:
                
                self.result.append(cur_path)
            return
        
        tmp_i, tmp_j = cur
        for i,j in [(tmp_i+1, tmp_j), (tmp_i -1, tmp_j), (tmp_i, tmp_j +1), (tmp_i, tmp_j -1)]:
            if 0 <= i < self.row and 0 <= j < self.col and not grid[i][j] == -1 and (i, j) not in cur_path:
                tmp_cur_path = list(cur_path)
                tmp_cur_path.append((i, j))
                self.helper(grid, (i, j), tmp_cur_path)


    def uniquePathsIII(self, grid: List[List[int]]) -> int:
        self.row = len(grid)
        self.col = len(grid[0])
        start = None
        self.end = None
        blocked = 0
        for i in range(self.row):
            for j in range(self.col):
                if grid[i][j] == 1:
                    start = (i, j)
                elif grid[i][j] == -1:
                    blocked += 1
                elif grid[i][j] == 2:
                    self.end = (i, j)
        
        self.path_len = self.row * self.col - blocked
        # DFS
        self.result = []
        self.helper(grid, start, [start])
        return len(self.result)

3.  839. 相似字符串组 https://leetcode-cn.com/problems/similar-string-groups/

考点: 深度搜索

class Solution:
    def fulfil(self, str1, str_list):
        str_len = len(str1)
        for str2 in str_list:
            diff = 0
            for i in range(str_len):
                if not str1[i] == str2[i]:
                    diff += 1
            if diff == 2 or diff == 0:
                return True
        return False

    def helper(self, A):
        if len(A) == 0:
            return

        found = False
        tmp_A = list(A)
        for s_str in A:
            for result in self.results:
                if self.fulfil(s_str, result):
                    found = True
                    result.append(s_str)
                    tmp_A.remove(s_str)
        
        if not found:
            tmp_str = A[0]
            self.results.append([tmp_str])
            tmp_A.remove(tmp_str)
        self.helper(tmp_A)
                    

    def numSimilarGroups(self, A: List[str]) -> int:
        self.results = []
        self.helper(A)
        return len(self.results)

 考虑优化,设置2级结果,已经遍历完全的组不参与遍历,继续超时

class Solution:
    def fulfil(self, str1, str_list):
        str_len = len(str1)
        for str2 in str_list:
            diff = 0
            for i in range(str_len):
                if not str1[i] == str2[i]:
                    diff += 1
            if diff == 2 or diff == 0:
                return True
        return False

    def helper(self, A):
        if len(A) == 0:
            self.results.append(self.results_tmp)
            self.results_tmp = []
            return

        found = False
        tmp_A = list(A)
        for s_str in A:
            if self.fulfil(s_str, self.results_tmp):
                found = True
                self.results_tmp.append(s_str)
                tmp_A.remove(s_str)
        
        if not found:
            tmp_str = A[0]
            if self.results_tmp:
                self.results.append(self.results_tmp)
                self.results_tmp = []
            tmp_A.remove(tmp_str)
            self.results_tmp.append(tmp_str)
            
        self.helper(tmp_A)
                    

    def numSimilarGroups(self, A: List[str]) -> int:
        self.results = []
        self.results_tmp = []
        self.helper(A)
        return len(self.results)

 想来想去,该种方法都需要 n *n 循环

    j继续优化,把字符窜分成一个个小类计算,还是时间超时,只能跑31 / 63 个通过测试用例

class Solution:  
    def fulfil(self, str1, str_list):
        str_len = len(str1)
        for str2 in str_list:
            diff = 0
            for i in range(str_len):
                if not str1[i] == str2[i]:
                    diff += 1
            if diff == 2 or diff == 0:
                return True
        return False

    def helper(self, A):
        if len(A) == 0:
            return 
 
        # 获取字符窜
        tmp_str = A[0]
        ori_list = [tmp_str]
        # 获取相似字符窜,删除
        A.remove(tmp_str)
        while ori_list:
            found = False
            tmp_list = []
            tmp_A = list(A)
            for a in tmp_A:
                if self.fulfil(a, ori_list):
                    found = True
                    tmp_list.append(a)
                    A.remove(a)
            ori_list = list(tmp_list)
            if not found:
                break
            
        # print(A)
        self.results += 1
        # 迭代
        self.helper(A)

    def numSimilarGroups(self, A: List[str]) -> int:
        # 时间超时,性能优化问题,首先想到是dict, 所以问题就变成使用什么样的key
        self.results = 0
        A_dict = collections.defaultdict(set)
        for a in A:
            A_dict["".join(sorted(a))].add(a)

        # print(A_dict)
        for value in A_dict.values():
            self.helper(list(value))
        # self.helper(A)
        return self.results

 

继续使用并查集优化,多通过一个用例,忧伤(32 / 63 个通过测试用例) 

class Solution:  
    def search(self, a, ilist):
        if ilist[a] != a:
            ilist[a] = self.search(ilist[a], ilist)
        return ilist[a]

    def union(self, a, b, ilist):
        aa = self.search(a, ilist)
        bb = self.search(b, ilist)
        # print("********")
        # print(a, aa)
        # print(b, bb)
        # print("%%%%%%%%%")
        if aa > bb:
            ilist[aa] = bb
        else:
            ilist[bb] = aa
        # print("****", ilist)


    def match(self, a, b):
        diff_len = 0
        for i in range(len(a)):
            if not a[i] == b[i]:
                diff_len += 1
        if diff_len == 2:
            return True
        return False

    def helper(self, str_list):
        if len(str_list) == 0:
            return 
 
        len_A = len(str_list)
        ilist = []
        ilist_dict = dict()
        for i in range(len_A):
            ilist.append(i)
            ilist_dict[str_list[i]] = i

        # print(ilist)
        # print(ilist_dict)
        for i in range(len_A-1):
            for j in range(i+1, len_A):
                if self.match(str_list[i], str_list[j]):
                    # print("&", ilist)
                    # print(i, j)
                    self.union(i ,j, ilist)
                    # print(ilist)
        
        for i in range(len(ilist)):
            self.search(i, ilist)
        self.results += len(set(ilist))



    def numSimilarGroups(self, A: List[str]) -> int:
        # 时间超时,性能优化问题,首先想到是dict, 所以问题就变成使用什么样的key
        self.results = 0
        A_dict = collections.defaultdict(set)
        for a in A:
            A_dict["".join(sorted(a))].add(a)

        # print(A_dict)
        for value in A_dict.values():
            self.helper(list(value))
        # self.helper(A)
        return self.results

514. 自由之路  https://leetcode-cn.com/problems/freedom-trail/

考点:

1、使用常规的 顺时针,逆时针的深度搜索,会超时

class Solution:
    def findRotateSteps(self, ring: str, key: str) -> int:
        # 1至100之间,值不大,尝试使用深度搜索
        ring_len = len(ring)
        key_len = len(key)
        result = set()
        result.add(float('inf'))
        def helper(ikey, cur_pos, cur_step):
            if not ikey:
                result.add(cur_step)
                return
            if cur_step > min(result):
                return
            
            if ring[cur_pos] == ikey[0]:
                helper(ikey[1:], cur_pos, cur_step)
                return
            
            # 顺时针
            for i in range(1, ring_len):
                if ikey[0] == ring[(cur_pos + i) % ring_len]:
                    helper(ikey[1:], (cur_pos + i) % ring_len, cur_step + i)
                    break
            # 逆时针
            for i in range(1, ring_len):
                if ikey[0] == ring[cur_pos - i]:
                    helper(ikey[1:], (cur_pos - i + ring_len) % ring_len, cur_step + i)
                    break




        helper(key, 0, 0)
        return min(result) + key_len

  

 

1、首先是一个最大值、最小值问题,然后根据前一个值,得到后一个值的最优解,可以使用动态规划

class Solution:
    def findRotateSteps(self, ring: str, key: str) -> int:
        ring_len = len(ring)
        key_len = len(key)

        grid = [[float('inf')] * ring_len for _ in range(key_len)]

        # 各元素的位置
        pos = collections.defaultdict(list)
        for i in range(ring_len):
            pos[ring[i]].append(i)
        # print(pos)

        def min_distance(x, y):
            if x > y:
                x, y = y, x
            return min(y-x, ring_len-(y-x))
        # 设置初始位置
        for index in pos[key[0]]:
            grid[0][index] = min_distance(0, index)
        
        for i in range(1, len(key)):
            for j in pos[key[i]]:
                for k in pos[key[i-1]]:
                    # print(grid)
                    grid[i][j] = min(grid[i][j], min_distance(k, j) + grid[i-1][k])
        return min(grid[-1]) + len(key)

  

 

posted @ 2020-11-04 23:30  哈哈哈喽喽喽  阅读(72)  评论(0编辑  收藏  举报