《热题100》回溯篇

《热题100》回溯篇_第1张图片

class Solution:

    def permuteUnique(self , num: List[int]) -> List[List[int]]:

        n = len(num)

        if n == 0:

            return []

        ans = []

        use = [False]*n

        def dfs(i,path):

            if i == n:

                ans.append(path.copy())

                return

            for j in range(n):

                if not use[j]:

                    path.append(num[j])

                    use[j] = True

                    dfs(i+1,path)

                    use[j] = False #恢复现场

                    path.pop()

        dfs(0,[])

        return ans

《热题100》回溯篇_第2张图片

class Solution:

    def permuteUnique(self , num: List[int]) -> List[List[int]]:

        n = len(num)

        if n == 0:

            return []

        ans = []

        use = [False]*n

        num = sorted(num) #为了最后是升序,先排列再找

        def dfs(i,path):

            if i == n:

                if path not in ans: #防止答案重复

                    ans.append(path.copy())

                return

            for j in range(n):

                if not use[j]:

                    path.append(num[j])

                    use[j] = True

                    dfs(i+1,path)

                    use[j] = False #恢复现场

                    path.pop()

        dfs(0,[])

        return ans

《热题100》回溯篇_第3张图片

思路:遍历二维数组,遇到1之后,就先给答案加1,然后进入递归,将1的上下左右都换成0,避免之后再进入。最后输出答案。

class Solution:

    def dfs(self,grid,i,j):

        if i >= len(grid) or i < 0: #判出条件

            return

        if j >= len(grid[0]) or j < 0:

            return

        if grid[i][j] == '1': #修改为'0'

            grid[i][j] = '0'

        else:

            return

        self.dfs(grid,i-1,j) #探寻上下左右

        self.dfs(grid,i+1,j)

        self.dfs(grid,i,j-1)

        self.dfs(grid,i,j+1)

    def solve(self , grid: List[List[str]]) -> int:

        n = len(grid)  #异常判断

        if n <= 0:

            return 0

        m = len(grid[0])

        if m <= 0:

            return 0

        ans = 0

        for i in range(n):

            for j in range(m):

                if grid[i][j] == '1':

                    self.dfs(grid,i,j)

                    ans += 1

        return ans

《热题100》回溯篇_第4张图片

思路:还是按照由相同数字的全排列,但是因为这次的数据量更大,所以需要先排序和剪枝。排序使相同的字母放在一起,如果当前两个字母相等,而且前一个字母已经被用了,那就跳出本次循环。

class Solution:

    def Permutation(self , s: str):

        n = len(s)

        if n == 0:

            return []

        ans = []

        use = [False]*n

        s = sorted(list(s)) #先排列

        def dfs(i,path):

            if i == n:

                ans.append(''.join(path.copy()))

                return

            for j in range(n):

                if not use[j]:

                    if j > 0 and s[j] == s[j-1] and use[j-1]: #剪枝

                        continue

                    use[j] = True

                    path.append(s[j])

                    dfs(i+1,path)

                    use[j] = False

                    path.pop()

        dfs(0,[])

        return ans

《热题100》回溯篇_第5张图片

 思路:单纯的深度递归会超时,因为之前会有大量的数据计算,所以需要一个数组来保存当前的最大递增路径的值。遍历数组,每遇到一个值都计算一次当前的最大递增路径,和答案比较,如果比答案大就更新答案。在遍历当前值时,如果当前dp值不是0,那就说明之前计算过该值,直接返回。否则开始计算,先让dp+1,然后从上下左右四个方向去更新dp。

class Solution:

    def path(self,matrix,i,j,dp):

        if dp[i][j] != 0:

            return dp[i][j]

        dp[i][j] += 1

        if i+1 >= 0 and i+1 < len(matrix) and matrix[i+1][j] > matrix[i][j]:

            dp[i][j] = max(dp[i][j],self.path(matrix,i+1,j,dp)+1)

        if i-1 >= 0 and i-1 < len(matrix) and matrix[i-1][j] > matrix[i][j]:

            dp[i][j] = max(dp[i][j],self.path(matrix,i-1,j,dp)+1)

        if j+1 >= 0 and j+1 < len(matrix[0]) and matrix[i][j+1] > matrix[i][j]:

            dp[i][j] = max(dp[i][j],self.path(matrix,i,j+1,dp)+1)

        if j-1 >= 0 and j-1 < len(matrix[0]) and matrix[i][j-1] > matrix[i][j]:

            dp[i][j] = max(dp[i][j],self.path(matrix,i,j-1,dp)+1)

        return dp[i][j]

    def solve(self , matrix: List[List[int]]) -> int:

        n = len(matrix)

        ans = 0

        if n == 0:

            return 0

        m = len(matrix[0])

        if m == 0:

            return 0

        dp = [[0]*m for _ in range(n)]

        for i in range(n):

            for j in range(m):

                ans = max(ans,self.path(matrix,i,j,dp))

        return ans

《热题100》回溯篇_第6张图片

 思路:每一行每一列都需要放入一个皇后,我们可以递归行号,然后在该行内,找列可以放的位置,如果都不冲突,就可以放入。然后记录列号,继续递归。需要用一个col[]记录每一行放入了哪一列。

class Solution:

    def Nqueen(self , n: int) -> int:

        col = [0]*n #下标表示行号,第row行放在了col[row]列

        ans = 0

        def dfs(row,s): #递归下一行和剩下可以取的列

            if row == n: #如果当前找到了最后一行

                nonlocal ans

                ans += 1

                return

            for c in s: #枚举剩下可以取的列

                #对于row之前的每一行,当前的取值row+c都不能等于之前的行号+列号

                #row-c也不能等于之前的行号-列号,才能保证不冲突

                if all(row+c != r+col[r] and row-c != r-col[r] for r in range(row)):

                    col[row] = c #如果不冲突,就记录下当前列

                    dfs(row+1,s-{c}) #继续递归下一行和剩下可以取的列

        dfs(0,set(range(n))) #列举列数[0,n-1]

        return ans    

插入一个题:输入几个json,将其中相同的地方合并,然后输出:

输入:

{'name':'hahha','id':123,'sci':'no'}
{'name': 'aaa', 'id': 12, 'sci': 'yes'}
{'name': 'hahha', 'id': 123, 'age': 11}
{'name': 'aaa', 'id': 12, 'age': 44}
{'name': 'bb', 'id': 56, 'age': 45}

输出:

{'name': 'hahha', 'id': 123, 'sci': 'no', 'age': 11}
{'name': 'aaa', 'id': 12, 'sci': 'yes', 'age': 44}
{'name': 'bb', 'id': 56, 'age': 45}

思路:用while true来获得输入的每一行json字符,将其用loads转换为字典。当输入是换行,就跳出循环。比较记录中的每个字典,如果有相同key和value,就合并(d1.update(d2)),然后删除多余的那个字典。用while循环来遍历记录,可以控制移动的下标。

import json

    d1 = []

    ans = []

    while True:

        data = input()

        if data != '':

            res = json.loads(data.replace("'",'"')) #单引号会导致loads出错,将单引号换成双引号

            d1.append(res)

        else:

            break

    def merge(dict1,dict2): #合并字典

        return (dict1.update(dict2))

    i= 0

    while i < len(d1)-1: #遍历该字典数组,遇到有相同部分的就合并

        j = i+1

        while j < len(d1):

            if any(d1[i][k] == d1[j][k] for k in d1[i] if k in d1[i] and k in d1[j]):

                merge(d1[i], d1[j])

                d1.remove(d1[j])

            else:

                j += 1

        i += 1

    for k in d1:

        print(k)

《热题100》回溯篇_第7张图片

思路:n对括号相当于在2n个位置上放置左括号和右括号。所以每个位置上都有选左括号和选右括号的可能。当l

class Solution:

    def generateParenthesis(self , n: int) -> List[str]:

        m = n*2

        if m == 0:

            return []

        ans = []

        def dfs(i,path,l,r):

            if i == m:

                ans.append(''.join(path.copy()))

                return

            if l < n: #选左括号

                path.append('(')

                dfs(i+1,path,l+1,r)

                path.pop()

            if r < l: #选右括号

                path.append(')')

                dfs(i+1,path,l,r+1)

                path.pop()

        dfs(0,[],0,0)

        return ans

 

你可能感兴趣的:(动态规划,算法)