首页 > 其他分享 >【力扣】复原IP地址(回溯法)(分割问题)

【力扣】复原IP地址(回溯法)(分割问题)

时间:2024-03-09 11:44:18浏览次数:13  
标签:pointNum return int IP地址 力扣 start result 回溯 size

问题描述

image
在这个题中,因为结果的数据类型为vector<string>所以直接在s中添加分割点比较方便,
先看一下代码:

class Solution {
private:
    vector<string> result;// 记录结果
    // startIndex: 搜索的起始位置,pointNum:添加逗点的数量
    void backtracking(string& s, int startIndex, int pointNum) {
        if (pointNum == 3) { // 逗点数量为3时,分隔结束
            // 判断第四段子字符串是否合法,如果合法就放进result中
            if (isValid(s, startIndex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }
        for (int i = startIndex; i < s.size(); i++) {
            if (isValid(s, startIndex, i)) { // 判断 [startIndex,i] 这个区间的子串是否合法
                s.insert(s.begin() + i + 1 , '.');  // 在i的后面插入一个逗点
                pointNum++;
                backtracking(s, i + 2, pointNum);   // 插入逗点之后下一个子串的起始位置为i+2
                pointNum--;                         // 回溯
                s.erase(s.begin() + i + 1);         // 回溯删掉逗点
            } else break; // 不合法,直接结束本层循环
        }
    }
    // 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法
    bool isValid(const string& s, int start, int end) {
        if (start > end) {
            return false;
        }
        if (s[start] == '0' && start != end) { // 0开头的数字不合法
                return false;
        }
        int num = 0;
        for (int i = start; i <= end; i++) {
            if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if (num > 255) { // 如果大于255了不合法
                return false;
            }
        }
        return true;
    }
public:
    vector<string> restoreIpAddresses(string s) {
        result.clear();
        if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了
        backtracking(s, 0, 0);
        return result;
    }
};

结束条件

在分割点的个数为3时,说明此时s已经被分割成了4部分,而且前三部分都是符合要求的,所以进入backtrace(s,startindex,3)后,就需要直接结束递归,不能再枚举了,只需要测试最后一段符不符合地址规范,符合的话就先保存结果再return,不符合的话就直接return
像这样:

if (pointNum == 3) { // 逗点数量为3时,分隔结束
            // 判断第四段子字符串是否合法,如果合法就放进result中
            if (isValid(s, startIndex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }

函数参数

这里的pointnum应该设为全局变量也可以,不一定要放在参数里

循环体内操作

            if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if (num > 255) { // 如果大于255了不合法
                return false;
            }
        }

这个操作和之前回文子串的基本一样。
OJ格式的代码:

#include<iostream>
#include<bits/stdc++.h> 
using namespace std;

vector<string> res;
int pointNum = 0;
bool isValid(string &s, int start, int end){
    //判断s在start-end的子串是否复合ip地址规范
    if(start > end){
        return false;
    }
    string tmp = s.substr(start, end - start +1);
    if(tmp.size() > 1 && tmp[0] == '0'){
        return false;
    }
    long long sum = 0;
    for(int i = 0; i < tmp.size(); i++){
        sum = sum*10 + (tmp[i] - '0');
    }
    return sum <= 255;
}
void backtrace(string &s, int startindex){
    if(pointNum == 3){
        if(isValid(s,startindex,s.size()-1)){
            res.push_back(s);
        }
        return ;
    } 

    for(int i = startindex; i < s.size(); i++){
        if(isValid(s,startindex,i)){
            s.insert(s.begin() + i + 1, '.');
            pointNum ++;
            backtrace(s,i+2);//因为多了一个分割点
            pointNum --;
            s.erase(s.begin() + i + 1);
        }else{
            break;
        }
    }
}
vector<string> restoreIpAddresses(string s) {
    res.clear();
    backtrace(s,0);
    return res;
}

int main(){
	string s;
	cin>>s;
	restoreIpAddresses(s);
	for(int i = 0; i < res.size(); i++){
		cout<<res[i]<<endl;
	}
	return 0;
}

标签:pointNum,return,int,IP地址,力扣,start,result,回溯,size
From: https://www.cnblogs.com/satsuki26681534/p/18062044

相关文章

  • 力扣回溯之 39. 组合总和
    //剪枝优化classSolution{  publicList<List<Integer>>combinationSum(int[]candidates,inttarget){    List<List<Integer>>res=newArrayList<>();    List<Integer>path=newArrayList<>();    A......
  • 【力扣】组合总和3(组合的去重)
    问题描述注意,如果数组里有两个元素的值相同,那么这两个元素是可以出现在同一个组合里的:但是:如果按前面的思路分析的话,会发现结果中出现很多相同的组合。像这样:这很明显是由于两个相同的1造成的,因为当前的startindex对应第一个1时,向下一层递归后,starindex定位的还是1,。如......
  • 【力扣】组合总数(回溯法)
    题目描述#include<iostream>#include<vector>usingnamespacestd;vector<vector<int>>res;vector<int>path;intaccumulate(vector<int>path){ intsum; for(inti=0;i<path.size();i++){ sum+=path[i]; } r......
  • 【力扣】电话号码的组合(回溯法)
    问题描述classSolution{public:vector<string>res;stringpath;//charA[26]={'a','b','c','d','e','f','g',//'h','i','j','k&......
  • 【力扣】求组合(回溯算法)
    题目描述2.以下是回溯算法的模版classSolution{private:vector<vector<int>>res;vector<int>path;//这个变量名还是设为path更合适voidbacktrace(intn,intk,intstartindex){//递归结束条件,这个是根据问题要求修改的if(path.s......
  • 力扣T26与T27的区别
    T27给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。T26你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一......
  • 【力扣】括号匹配(栈的应用)
    题目描述顾名思义代码如下:#include<iostream>#include<string>#include<stack>usingnamespacestd;boolisValid(strings){ if(s.empty()){ returntrue; } if(s.size()%2!=0){ returnfalse; } inti=0; stack<char>st; while(i<......
  • AndroidStudio扫描局域网下的ESP32CAM并获取IP地址
    大概想法如下: 在ESP32CAM端直接下载示例代码udp_server这个历程,修改默认的WIFI和密码,启动之后会输出如下结果 由此我们知道了UDP的地址和端口IP地址为192.168.2.3,端口为3333此时我们使用小工具NetAssist.exe来测试,选择UDP协议之后向ESP32CAM的地址发送广播,如下图所示 ......
  • 力扣781.森林中的兔子
    题目:森林中有未知数量的兔子。提问其中若干只兔子"还有多少只兔子与你(指被提问的兔子)颜色相同?",将答案收集到一个整数数组answers中,其中answers[i]是第i只兔子的回答。给你数组answers,返回森林中兔子的最少数量。实现方法:由于要求兔子最少数量,可以假定答案相同的......
  • 力扣88.合并两个有序数组
    题目:给你两个按非递减顺序排列的整数数组nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。请你合并nums2到nums中,使合并后的数组同样按非递减顺序排列。注意:最终,合并后数组不应由函数返回,而是存储在数组nums1中。为了应对这种情况,nums1的初始长度为m+n......