代码随想录算法训练营第28天 | LeetCode93.复原IP地址,78.子集,90.子集II

@代码随想录算法训练营第28天 | LeetCode93.复原IP地址,78.子集,90.子集II

93.复原IP地址

第一遍读题思考

问题可以翻译成在给定的字符串中插入三个“.”,所以在回溯的树结构中,每一层都是插入一个节点

代码随想录解法思路

难点在于如何perform插入这个操作,需要额外的path吗?不需要,只需要在原s上插入’.'然后再回溯就可以了。
还需要注意如何判断一段字符串是否是合法的,需要考虑字符串长度不为0时首字母为0是不对的,字母中有0-9之外的数是不对的,然后字符串所代表的整数是大于255也是不对的。

c++代码具体实现注意事项

注意字符串在特定位置插入是怎么操作的?

(递归版本)
class Solution {
public:
    vector<string> result;
    void traversal(string& s, int start, int pointNum){
        if(pointNum==3){
            if(isValid(s, start, s.size()-1)){
                result.push_back(s);
            }
            return;
        }
        for(int i=start;i<s.size();i++){
            if(isValid(s,start,i)){
                s.insert(s.begin()+i+1, '.');
                pointNum++;
                traversal(s, i+2, pointNum);
                pointNum--;
                s.erase(s.begin()+i+1);
            }
            else break;
        }
    }

    bool isValid(string s, int start, int end){
        if(start>end) return false;
        if(start<end && s[start]=='0'){
            return false;
        }
        int num=0;
        num = s[start]-'0';
        for(int i=start+1;i<=end;i++){
            if(s[i]>'9' || s[i]<0){
                return false;
            }
            num=(num*10+(s[i]-'0'));
            if(num>255) return false;
        }
        return true;
    }
    vector<string> restoreIpAddresses(string s) {
        traversal(s, 0, 0);
        return result;
    }
};

78. 子集

第一遍读题思考

按照分割的思路来进行就涉及到要切几刀的问题,按照子集长度的思路来有涉及到几种不同的长度。

代码随想录解法思路

这道题是回溯问题中的第三类问题(前两个分别是组合问题和分割问题),这个叫做子集问题。与之前的不同是,前面的问题都是收集树的叶子节点,而子集问题是收集所有的节点.也就是按照最基本的回溯模板进行遍历,然后存储每个节点上的子集

c++代码具体实现注意事项

(递归版本)
class Solution {
public:
    vector<vector<int>> result;
    vector<int> subset;
    
    void tra(vector<int> nums, int begin){
        result.push_back(subset);
        if(begin==nums.size()){
            return;
        }
        for(int i=begin;i<nums.size();i++){
            subset.push_back(nums[i]);
            tra(nums, i+1);
            subset.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        tra(nums, 0);
        return result;
    }
};

90.子集||

第一遍读题思考

去重操作跟40.组合总和||是一样的,同层不可取相同,排序进行比较前一项即可。

代码随想录解法思路

一样

c++代码具体实现注意事项

在这里插入图片描述

(递归版本)
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void tra(vector<int> nums, int start){
        result.push_back(path);
        if(start==nums.size()){
            return;
        }
        for(int i=start;i<nums.size();i++){
            if(i>start && nums[i]==nums[i-1]){
                continue;
            }
            path.push_back(nums[i]);
            tra(nums, i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        tra(nums, 0);
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值