代码随想录算法训练营day28|Leetcode93/78/90

Leetcode93

https://leetcode.cn/problems/restore-ip-addresses/

有效 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 中的任何数字。你可以按 任何 顺序返回答案。

思路:

说实话 这道题没太懂。。。。

等我二刷再来啃

Leetcode78子集

https://leetcode.cn/problems/subsets/

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

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

思路:

如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!

其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。

那么既然是无序,取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始!

什么时候for可以从0开始呢?

求排列问题的时候,就要从0开始,因为集合是有序的,{1, 2} 和{2, 1}是两个集合。

同时 转换成树形结构来看这道题,一共有两个维度需要考虑,一个是树层去重,一个是树枝去重。

如图所示:

 

回溯三部曲:

                递归参数:nums,startindex表示下一次循环从哪儿开始 

                 终止条件:如果startindex的位置已经超出了我们数组的长度,就代表已经数组中的元素已经取完了,就直接return

                单层循环逻辑:每次递归i要从i+1的位置开始搜索,因为我们一个元素不能使用多次

代码:

def subsets(self, nums: List[int]) -> List[List[int]]:
        result = []
        path = []
        def traversal(nums,startindex):
            #这里是浅拷贝 !!!!!赋值的是地址 有一个大坑
            result.append(path[:])
            #递归终止条件
            if startindex >=len(nums):
                return 
            for i in range(startindex,len(nums)):
                path.append(nums[i])
                traversal(nums,i+1)
                path.pop()
        traversal(nums,0)
        return result

Leetcode90子集

力扣

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

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

思路:首先这道题是有一个重复的元素,并且要求不能有重复的子集,那么就说明了这里会产生一个去重的逻辑,既然是有去重,还有数组,那么首先要对数组进行一个排序的操作,这样子相邻的元素才会挨在一起,方便我们对去重做出判断

同时,和上一道题一样我们转换为树形结构的思路来想,这里有两个维度需要考虑。一个是树枝,一个是树层

 从图中可以看出,我们的树枝部分是可以取重复元素的,但是树层不可以取重复元素,也就是说我们的去重逻辑应该放在for循环的下面,当前元素如果等于前一个元素,并且i>startindex的时候

我们跳过本次循环。这就是本题最关键的去重部分

 def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        result = []
        path = []
        def traversal(nums,startindex):
            nums.sort()
            result.append(path[:])
            #终止条件
            if startindex>=len(nums):
                return 
            for i in range(startindex,len(nums)):
                if i > startindex and nums[i]==nums[i-1]:
                    continue 
                path.append(nums[i])
                traversal(nums,i+1)
                path.pop()
        traversal(nums,0)
        return result
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值