Leetcode 学习计划之21天算法 (十一)

第11天:递归、回溯

77. 组合

1、全部组合字眼,考虑回溯法。回溯法模板:(这里注意python中递归使用list时要用切片引用(浅复制),patch[:],而不用patch[]。很多题都是这样的,要用切片的浅复制。

时间复杂度:O(2^n)
空间复杂度:O(n + k) = O(n)O(n+k)=O(n),即递归使用栈空间的空间代价和临时数组temp 的空间代价。

这个时候我们可以做一个剪枝,如果当前path的大小为 s,未确定状态的区间 [starIndex,n] 的长度为 t,如果 s+t<k,那么即使 t 个都被选中,也不可能构造出一个长度为 k 的序列,故这种情况就没有必要继续向下递归,即我们可以在每次递归开始的时候做一次这样的判断:

if (path.size() + (n - starIndex + 1) < k) {
    return;
}

void backtracking(参数) {
    if (终止条件) {
        存放结果;       //result.append(path[:])
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;       //path.append(i)
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果 path.pop()
    }
}

class Solution(object):
    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        patch = []
        result = []
        def backtracking(n,k,startIndex):
            if len(patch) == k:
                result.append(patch[:])
                return
            for i in range(startIndex,n+1):
                patch.append(i)
                backtracking(n,k,i+1)
                patch.pop()

        backtracking(n,k,1)
        return result

46.全排列

回溯法模板: 只是在对传递的参数修改,原来为index+1,这里是除了当前值外的nums值,(正是当前树层的子节点,如当前值为1,下一层就是2,3]。

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        l = len(nums)
        res = []
        path = []
        def backtracking(num):
            if len(path) == l:
                res.append(path[:])
                return
            for i in range(len(num)):
                path.append(num[i])
                t = [num[x] for x in range(len(num)) if x!= i]
                backtracking(t)
                path.pop()
        backtracking(nums)
        return res

784.字母大小写全排列

思路: 

1、回溯法:但是不用for循环了(当前层的孩子节点要么是1要么是2,不是像“组合”题目一样数目是变化的,从n-1到n-2...到0),用if就行了。数字后面也要回溯,不能省略。

2、回溯法:用dfs写法,不用显示的写pop(),不用path,直接在参数中传入tmp+s[index],这样就避免对path做显示的出入栈操作了。

class Solution(object):
    def letterCasePermutation(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        path = []
        res = []
        l = len(s)
        def backtracking(index):
            if len(path[:]) == l:
                res.append(''.join(path))
                return
            if '0'<= s[index] <='9' :
                path.append(s[index])
                backtracking(index+1)
                path.pop()
            else:
                path.append(s[index].lower())
                backtracking(index+1)
                path.pop()

                path.append(s[index].upper())
                backtracking(index+1)
                path.pop()                

        backtracking(0)  
        return res               
class Solution(object):
    def letterCasePermutation(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        res = []
        l = len(s)
        def backtracking(tmp,index):
            if len(tmp) == l:
                res.append(tmp)
                return
            if '0' <= s[index] <= '9':
                backtracking(tmp+s[index],index+1)
            else:
                backtracking(tmp+s[index].lower(),index+1) 
                backtracking(tmp+s[index].upper(),index+1) 
        backtracking('', 0)  
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值