leetcode-回溯

目录

组合(N个数里面按一定规则找出k个数的集合) 

77. 组合

17. 电话号码的数字组合

39.组合总和

40. 组合总和ii

216. 组合总和iii

分割(一个字符串按一定规则有几种切割方式)

131. 分割回文串

93. 复原IP地址

子集(一个N个数的集合里有多少符合条件的子集)

78. 子集

90. 子集ii

排列(N个数按一定规则全排列,有几种排列方式)

46. 全排列

47. 全排列ii

棋盘

51. N皇后

37. 解数独

其他

491. 递增子序列

332. 重新安排行程


组合(N个数里面按一定规则找出k个数的集合) 

组合不强调元素顺序,排列强调元素顺序

77. 组合

class Solution(object):
    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        # index为即将确定第index位数字
        # pre为之前已经排序过的数字
        # 这种组合方式默认从小到大排列,因此ans中的数字应该是由小到大的
        def backtracking(index, ans, res, pre):
            if index == k:
                res.append(ans)
            for i in range(pre+1, n+1):
                backtracking(index + 1, ans + [i], res, i)

        ans = []
        res = []
        backtracking(0, ans, res, 0)
        return res

17. 电话号码的数字组合

class Solution(object):
    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        if not digits:
            return []

        hashtable = {
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz",
        }

        def backtrack(index, ans, res):
            if index == len(digits):
                res.append("".join(ans))
            else:
                digit = digits[index]
                for letter in hashtable[digit]:
                    backtrack(index + 1, ans + [letter], res)

        ans = []
        res = []
        backtrack(0, ans, res)
        return res

39.组合总和

class Solution:
    def combinationSum(self, candidates, target):
        def dfs(begin, ans, res, target):
            # begin存储遍历起点,避免重复遍历
            if target == 0:
                res.append(ans)
                return
            for index in range(begin, size):
                residue = target - candidates[index]
                if residue < 0:
                    break
                dfs(index, ans + [candidates[index]], res, residue)

        size = len(candidates)  # 决定树的宽度
        if size == 0:
            return []
        candidates.sort()
        ans, res = [], []
        dfs(0, ans, res, target)
        return res

40. 组合总和ii

class Solution:
    def combinationSum2(self, candidates, target):
        def dfs(begin, ans, res, target):
            # begin存储遍历起点,避免重复遍历
            if target == 0:
                res.append(ans)
                return
            for index in range(begin, size):
                residue = target - candidates[index]
                if residue < 0:
                    break
                if index > begin and candidates[index] == candidates[index-1]:
                    continue
                dfs(index + 1, ans + [candidates[index]], res, residue)

        size = len(candidates)  # 决定树的宽度
        if size == 0:
            return []
        candidates.sort()
        ans, res = [], []
        dfs(0, ans, res, target)
        return res

216. 组合总和iii

class Solution(object):
    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """

        def backtracking(index, ans, res, target, pre):
            if index == k:
                if target == 0:
                    res.append(ans)
                return
            for val in range(pre+1, min(target+1, 10)):
                if target - val < 0:
                    break
                backtracking(index+1, ans + [val], res, target-val, val)

        ans, res = [], []
        backtracking(0, ans, res, n, 0)
        return res

分割(一个字符串按一定规则有几种切割方式)

131. 分割回文串

class Solution(object):
    def partition(self, s):
        """
        :type s: str
        :rtype: List[List[str]]
        """

        def backtracking(start, ans, res):
            if start == len(s):
                res.append(ans)
                return
            for stop in range(start + 1, len(s) + 1):
                if is_valid(s[start:stop]):
                    backtracking(stop, ans + [s[start: stop]], res)

        def is_valid(tmp):
            if len(tmp) == 1: return True
            left, right = 0, len(tmp) - 1
            while left < right:
                if tmp[left] != tmp[right]: return False
                left += 1
                right -= 1
            return True

        ans, res = [], []
        backtracking(0, ans, res)
        return res

93. 复原IP地址

class Solution(object):
    def restoreIpAddresses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        res = []  # 保存所有ip
        ans = ''  # 保存当前ip

        # start:第start位的数据还未划分
        # times:即将进行第times次划分
        def recur(start, times, ans, res):
            if times == 4:
                res.append(ans)
                return
            for i in range(1, 4):
                tmp = s[start:start+i]  # 划分出的下一字段
                tmp_value = int(tmp)
                # 1. 划分字段值大于255
                # 2. 划分字段为‘0x’形式或‘0xx’形式或‘00x’形式
                # 3. 划分字段之后剩余的位数太多/太少无法划分
                if tmp_value > 255 or (i > 1 and tmp[0] == '0') \
                        or len(s) - start - i > 3 * (3-times) \
                        or len(s) - start - i < 3 - times:
                    continue
                else:
                    if start == 0:
                        recur(start+i, times+1, ans + tmp, res)
                    else:
                        recur(start + i, times + 1, ans + '.' + tmp, res)

        recur(0,0,ans,res)
        return res

子集(一个N个数的集合里有多少符合条件的子集)

78. 子集

class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def backtracking(start, ans, res):
            if start == len(nums):
                res.append(ans)
                return
            backtracking(start + 1, ans + [nums[start]], res)
            backtracking(start + 1, ans, res)

        ans, res = [], []
        backtracking(0, ans, res)
        return res

90. 子集ii

class Solution(object):
    def subsetsWithDup(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def backtrack(start, ans, res):
            res.append(ans)
            for i in range(start, len(nums)):
                if i > start and nums[i] == nums[i - 1]:
                    continue
                backtrack(i + 1, ans + [nums[i]], res)

        nums.sort()
        ans, res = [], []
        backtrack(0, ans, res)
        return res

排列(N个数按一定规则全排列,有几种排列方式)

组合不强调元素顺序,排列强调元素顺序

46. 全排列

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def dfs(used, ans, res):
            if len(ans) == size:
                res.append(ans)
                return
            for index in range(size):
                if used[index] == 1:
                    continue
                used[index] = 1
                dfs(used, ans + [nums[index]], res)
                used[index] = 0

        size = len(nums)
        ans, res = [], []
        used = [0 for _ in range(size)]
        nums.sort()
        dfs(used, ans, res)
        return res
# 交换
class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """

        def backtrack(index):
            if index == n:
                res.append(nums[:])
                return
            for i in range(index, n):
                nums[index], nums[i] = nums[i], nums[index]
                backtrack(index + 1)
                nums[index], nums[i] = nums[i], nums[index]

        n = len(nums)
        res = []
        backtrack(0)
        return res

47. 全排列ii

class Solution:
    def permuteUnique(self, nums):
        def dfs(used, ans, res):
            if len(ans) == size:
                res.append(ans)
                return
            for index in range(size):
                if used[index] == 1:
                    continue
                if index > 0 and nums[index] == nums[index-1] and used[index-1] == 0:
                    continue
                used[index] = 1
                dfs(used, ans + [nums[index]], res)
                used[index] = 0

        size = len(nums)
        ans, res = [], []
        used = [0 for _ in range(size)]
        nums.sort()
        dfs(used, ans, res)
        return res
# 交换
class Solution:
    def permuteUnique(self, nums):
        def dfs(start):
            if start == len(nums):
                res.append(nums[:])
            for i in range(start, len(nums)):
                if i > start and nums[i] == nums[i - 1]: continue
                nums[start], nums[i] = nums[i], nums[start]
                dfs(start + 1)
                nums[start], nums[i] = nums[i], nums[start]

        res = []
        dfs(0)
        return res

棋盘

51. N皇后

class Solution:
    def solveNQueens(self, n):
        if not n: return []
        board = [['.'] * n for _ in range(n)]
        res = []
        def isVaild(board,row, col):
            #判断同一列是否冲突
            for i in range(len(board)):
                if board[i][col] == 'Q':
                    return False
            # 判断左上角是否冲突
            i = row -1
            j = col -1
            while i>=0 and j>=0:
                if board[i][j] == 'Q':
                    return False
                i -= 1
                j -= 1
            # 判断右上角是否冲突
            i = row - 1
            j = col + 1
            while i>=0 and j < len(board):
                if board[i][j] == 'Q':
                    return False
                i -= 1
                j += 1
            return True

        def backtracking(board, row, n):
            # 如果走到最后一行,说明已经找到一个解
            if row == n:
                temp_res = []
                for temp in board:
                    temp_str = "".join(temp)
                    temp_res.append(temp_str)
                res.append(temp_res)
            for col in range(n):
                if not isVaild(board, row, col):
                    continue
                board[row][col] = 'Q'
                backtracking(board, row+1, n)
                board[row][col] = '.'
        backtracking(board, 0, n)
        return res

37. 解数独

class Solution(object):
    def solveSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: None Do not return anything, modify board in-place instead.
        """
        def is_valid(cur_x, cur_y, board, val):
            # row
            for i in range(9):
                if board[i][cur_y] == str(val) and i != cur_x:
                    return False
            # col
            for j in range(9):
                if board[cur_x][j] == str(val) and j != cur_y:
                    return False
            # square
            row_range = (cur_x // 3) * 3
            col_range = (cur_y // 3) * 3
            for i in range(row_range, row_range+3):
                for j in range(col_range, col_range+3):
                    if board[i][j] == str(val) and i != cur_x and j != cur_y:
                        return False
            return True

        def recur(board):
            for i in range(9):
                for j in range(9):
                    if board[i][j] != '.':
                        continue
                    for k in range(1,10):
                        if is_valid(i, j, board, k):
                            board[i][j] = str(k)
                            if recur(board): return True
                            board[i][j] = '.'
                    return False
            return True

        if recur(board):
            return board
        else:
            return

其他

491. 递增子序列

class Solution:
    def findSubsequences(self, nums) :
        res = []
        path = []
        def backtrack(nums,startIndex):
            # 这里使用数组来进行去重操作
            repeat = []
            if len(path) >= 2:
                res.append(path[:])
                # 注意这里不要加return,要取树上的节点
            for i in range(startIndex,len(nums)):
                if nums[i] in repeat:
                    continue
                if len(path) >= 1:
                    if nums[i] < path[-1]:
                        continue
                # 记录这个元素在本层用过了,本层后面不能再用了
                repeat.append(nums[i])
                path.append(nums[i])
                backtrack(nums,i+1)
                path.pop()
        backtrack(nums,0)
        return res

332. 重新安排行程

class Solution(object):
    def findItinerary(self, tickets):
        """
        :type tickets: List[List[str]]
        :rtype: List[str]
        """
        # hashtable的key是出发地departure,value是目的地destination
        hashtable = collections.defaultdict(list)
        for val in tickets:
            hashtable[val[0]].append(val[1])

        def backtracking(i, start, ans):
            if i == n:
                return True
            for index in range(len(hashtable[start])):
                hashtable[start].sort()
                destination = hashtable[start].pop(index)
                ans.append(destination)
                if backtracking(i+1, destination, ans):
                    return True
                ans.pop(-1)
                hashtable[start].append(destination)

        ans = ['JFK']
        n = len(tickets) + 1
        backtracking(1, 'JFK', ans)
        return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值