day28| 93+78+90

93.复原ip地址

 

题目简述:

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

 

思路:

1. 取出前几个字符,检测合法性

2. 如果合法,把这些个字符当作第一段,问题变成了把剩余字符串分为剩余段数

3. 不合法,直接return

4. 到了分最后一段的时候,直接检测剩余的字符串的合法性,合法了,那就多了一种组合

 

代码如下:

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        # 1. 依次检查字符是否合法,是不是数字,在不在特定范围
        # 2. 检查分割次数;到了最后一次分割次数,直接把检测剩余字符串的合法性
        res=[]
        path=[]
        n=len(s)
        def is_legal(arr):
            if arr.isdigit():
                if int(arr)>=0 and int(arr)<=255:
                    if len(arr)>1 and arr[0]=='0':# 这里别写成了arr[0]==0,字符肯定不等于0
                        return False
                    else:
                        return True
                else:
                    return False
            return False
        


        
        def dfs(begin,path,depth):
            if depth==3:
                if is_legal(s[begin:]):
                    path.append(s[begin:])
                    res.append(''.join(i for i in path))
                    path.pop()# 要注意恢复原样
                    return 
                return

            for i in range(begin+1,n):
                if is_legal(s[begin:i]):
                    path.append(s[begin:i])
                    path.append(".")
                    dfs(i,path,depth+1)
                    path.pop()
                    path.pop()
                else:
                    return
            return
        
        dfs(0,[],0)
        return res

 

78.子集

 

题目简述:

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

 

思路:

1. 分为元素在自己中,不在自己中,两种情况

 

代码:

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 1. 从左至右遍历,分为在子集中,不在子集中两种情况
        n=len(nums)
        res=[]

        def dfs(path,depth):
            if depth==n:
                res.append(path[:])
                return # 不要忘记return
            
            dfs(path,depth+1)
            path.append(nums[depth])
            dfs(path,depth+1)
            path.pop()
            return
        
        dfs([],0)
        return res

 

 

90. 子集II

 

题目简述:

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

 

思路:

我们从左向右往子集增加元素,到头了就回溯,把子集的最后一个元素删去,再从该最后元素对应的原数组位置的下一个位置开始遍历,考虑重复情况进行跳过

 

1. 考虑数组[1,2,3],选择前两个数,或者第一/三个数,都会得到相同的子集

2. 也就是说,对于当前选择的数x,若前面有与其相同的数y,且没有选择y,此时若把x放入自己中,会发现该情况我们已经考虑过了

3. 这是需要条件判断语句来跳过这种情况

 

代码:

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        def backtrack(begin,size,path,used):

            res.append(path[:])

            for i in range(begin,size):
                if used[i-1]==False and nums[i]==nums[i-1] and i>0:
                    continue
                used[i]=True
                backtrack(i+1,size,path+[nums[i]],used)
                used[i]=False
        
        size=len(nums)
        nums.sort()
        res,path=[],[]
        used=[False for _ in range(size)]
        backtrack(0,size,path,used)
        return res

 

 

总结:

1. 先写dfs函数,参数可以先不确定,可以一边写一些确定参数

2. 停止条件也可以先写好函数的正常情况,再来考虑特殊情况

3. 如果特殊情况比较多,可以进行细致地分类

4. 这些dfs函数并没有返回值,都是直接在函数终止条件里,把要做的事情都给做了

 

posted @ 2023-04-13 19:14  blueCP1999  阅读(47)  评论(0)    收藏  举报