代码随想录算法训练营第二十八天| LeetCode93.复原IP地址、LeetCode78.子集、LeetCode90.子集II

93.复原IP地址

题目描述: 93.复原IP地址.

解法

回溯
class Solution(object):
    def is_vaild(self,start,end,path):
        len_num = end - start
        last_num = self.length - end
        last_floor = 4-len(path)-1
        if last_num>0 and last_floor >0 and last_num/last_floor > 3:
            return False
        if last_num > 0 and last_floor <=0:
            return False
        if last_floor > 0 and last_num <=0:
            return False
        if len_num > 1 and self.s[start] == '0':
            return False
        if int(self.s[start:end]) >255:
            return False
        return True

    def backtrack(self,start,path):
        if start == self.length and len(path) == 4:
            self.res.append('.'.join(path))
            return
        for i in range(start+1,min(start+4,self.length+1)):
            if self.is_vaild(start,i,path):
                path.append(self.s[start:i])
                self.backtrack(i,path)
                path.pop()

    def restoreIpAddresses(self, s):
        self.s = s
        self.length = len(s)
        self.res = []
        self.backtrack(0,[])
        return self.res

本质上还是字符串的分割,但是多了一些限制条件,这些限制条件可以在进入回溯之前continue或者进入回溯之后return来完成
主要是以下限制条件,这些限制条件也完成了对回溯的剪枝:
1.每一个子串的位数如果大于1,那么第一位不可以是0
2.每一个子串的位数不大于3
3.如果当前子串取完数字,已经达到了4位ip地址,而还有剩下的子串,直接return
4.如果当前已经没有剩下的子串,但是还不够4位ip,直接return
5.如果剩下子串的长度除以还需要填补的位置大于3,则直接return
筛去以上条件,最后返回时可以直接用无剩余子串并且path长度为4为条件,将path用.进行连接,加入到res中

78.子集

题目描述: 78.子集.

解法

回溯
class Solution(object):
    def backtrack(self,start,path):
        self.res.append(path[:])
        for i in range(start,self.length):
            path.append(self.nums[i])
            self.backtrack(i+1,path)
            path.pop()
        
    def subsets(self, nums):
        self.nums = nums
        self.length = len(nums)
        self.res = []
        self.backtrack(0,[])
        return self.res

子集也是求组合的方式,只不过每次回溯的时候都要将当前的path加入到res中,注意传递给下层回溯的start应该是当前的i+1,这样可以避免重复遍历。

90.子集II

题目描述: 90.子集II.

解法

回溯
class Solution(object):
    def backtrack(self,start,path):
        self.res.append(path[:])

        for i in range(start,self.length):
            if i > start and self.nums[i] == self.nums[i-1]:
                continue
            path.append(self.nums[i])
            self.backtrack(i+1,path)
            path.pop()

    def subsetsWithDup(self, nums):
        self.nums = nums
        self.nums.sort()
        self.length = len(nums)
        self.res = []
        self.backtrack(0,[])
        return self.res

由于遍历的数组中会出现重复的元素,所以最后遍历的结果也有可能发生重复的现象,为了避免重复,还是先将数组排序然后避免重复遍历,一定要记住每次遍历的i一定要先大于起点,然后再判断是不是和上一个重合。

你可能感兴趣的:(算法,python,开发语言)