首页 > 其他分享 >力扣-93-复原IP地址

力扣-93-复原IP地址

时间:2023-04-06 21:59:32浏览次数:70  
标签:index string int 力扣 str IP地址 93 addr

直达链接

之前我写过一次IP地址转二进制

好吧,读完题发现好像和这题没什么关系

给一串数字中加.,返回所有的能够构成合法IP地址的结果

有点回溯的味道,但是却又和之前的排列组合不太一样:

  1. 其实相当于划分4个空往里填数字,但是这里每个空中的数字长度是不确定的
  2. 填入数字是会有额外的两个条件限制

尝试了但是不好写

class Solution {
public:
    vector<string> res;

    /*
    * 回溯子函数,n表示:输入长度,k表示:输出长度
    * index表示要填的空,只有四个空,并且每填完一个空就要加一个.,最后一个除外
    */
    void backTrace(string& str,string& temp, int n, int index) {
        // 只要不是第一次,就为每一次划分补一个.
        if (index != 0) temp.push_back('.');
        // 出口条件:等于加了三个.的长度
        if (temp.size() == n + 3) {
            res.push_back(temp);
            return;
        }
        // 递归划分
        int i = index;
        while (i < n) {
            // 对于每一个空,可以依次塞1个、2个、3个数字
            for (int j = 0; j < 3; j++) {
                temp.push_back(str[i]);
                backTrace(str, temp, n, ++i);
            }
            for (int j = 0; j < 3; j++) {
                temp.pop_back();
            }
        }
    }
    /*
    * 给定一个由数字构成的字符串,给它们之间加点分隔,返回所有合法的IP地址
    * 1. 不能有先导0
    * 2. 每个部分数字范围0-255
    */
    vector<string> restoreIpAddresses(string s) {
        // 字符串长度范围为[1,20],而IP地址的合法长度为[4,12]
        int len = s.length();
        if (len < 4 || len>12) return {};
        // 将字符串划分为4个部分,回溯
        string temp;
        backTrace(s,temp, len, 0);
    }
};

看一眼题解,思路:

相当于对一段字符串进行划分,用回溯分四段
首先我们需要一个存储所有结果的字符串数组,
其次需要一个临时容器用来存储每一次的可能结果,这里用的是一个整型数组,这个数组的长度会被定为4(4段),每一段会被转成一个整型数字(因为没有先导0,所以这么做没有问题)

我们的回溯函数参数有三个,1是原始字符串,我们需要用另一个指针参数来遍历这个字符串,最后是一个counter,用来记我们已经划分了几段(这是必要的)

回溯函数

首先我们需要定义函数的出口条件:1. 遍历完整个字符串没有遗漏 2. 已经划分四段,不多不少

  • 1满足2不满足/2满足1不满足:
    提前用完了还没划分四段,pass;
    已经划分了四段但是还有剩,pass

  • 1满足2满足:
    将整数数组的4段以点连接拼成一个字符串压入结果集

			if (index == str.size()) {
				string ipAddr;
				// 虽然是4次循环,但是有可能为空,相当于清空缓存并转换为一段IP
				// 这是在拼整个IP地址,4段?但是segment[i]难道不只是一个数字?后面对字符做了处理
				for (int i = 0; i < SEG_COUNT; ++i) {
					ipAddr += to_string(segments[i]);
					// 最后一段不加.
					if (i != SEG_COUNT - 1) ipAddr += '.';
				}
				// move函数旨在提高性能,非必要
				res.push_back(move(ipAddr));
  • 先导0检查
		/*
		* 不能有先导0,于是当遇到0的时候这一段只能是0
		*/
		if (str[index] == '0') {
			segments[turn] = 0;
			backTrace(str, turn + 1, index + 1);
		}
  • 1不满足,2不满足:
    字符串还没遍历完,也还没划分满4段
    从index标记位置开始每次压一位(连接之前的转成整数),设置为当前段值,递归下一个位置,当超过合法返回结束loop
		int addr = 0;
		for (int end = index; end < str.size(); ++end) {
			addr = addr * 10 + (str[end] - '0');
			if (addr > 0 && addr <= 0xFF) {
				segments[turn] = addr;
				backTrace(str, turn + 1, end + 1);
			}
			else break;
		}

完整代码

class Solution {
private:
	static constexpr int SEG_COUNT = 4;
	vector<string> res;
	vector<int> segments;// 保存了四段中任意一段的内容
public:

	/*
	* 回溯子函数,n表示:输入长度,k表示:输出长度
	* index表示要填的空,只有四个空,并且每填完一个空就要加一个.,最后一个除外
	*/
	void backTrace(string& str, int turn, int index) {
		// 出口条件:找到了4段IP地址,并且遍历完了字符串
		if (turn == SEG_COUNT) {
			if (index == str.size()) {
				string ipAddr;
				// 虽然是4次循环,但是有可能为空,相当于清空缓存并转换为一段IP
				// 这是在拼整个IP地址,4段?但是segment[i]难道不只是一个数字?后面对字符做了处理
				for (int i = 0; i < SEG_COUNT; ++i) {
					ipAddr += to_string(segments[i]);
					// 最后一段不加.
					if (i != SEG_COUNT - 1) ipAddr += '.';
				}
				// move函数旨在提高性能,非必要
				res.push_back(move(ipAddr));
			}
			// 如果已经生成了四段,但是没有遍历完,就不是合法的地址,舍弃
			return;
		}

		// 没有找满4段就遍历完了
		if (index == str.size()) return;

		/*
		* 不能有先导0,于是当遇到0的时候这一段只能是0
		*/
		if (str[index] == '0') {
			segments[turn] = 0;
			backTrace(str, turn + 1, index + 1);
		}

		// 一般情况
		int addr = 0;
		for (int end = index; end < str.size(); ++end) {
			addr = addr * 10 + (str[end] - '0');
			if (addr > 0 && addr <= 0xFF) {
				segments[turn] = addr;
				backTrace(str, turn + 1, end + 1);
			}
			else break;
		}
	}
	/*
	* 给定一个由数字构成的字符串,给它们之间加点分隔,返回所有合法的IP地址
	* 1. 不能有先导0
	* 2. 每个部分数字范围0-255
	*/
	vector<string> restoreIpAddresses(string s) {
		// 这里其实不写长度检查,非法长度也会在后面被筛除
		/*int len = s.length();
		if (len < 4 || len>12) return {};*/
		// 将字符串划分为4个部分,回溯
		segments.resize(SEG_COUNT);
		backTrace(s, 0, 0);
		return res;
	}
};

标签:index,string,int,力扣,str,IP地址,93,addr
From: https://www.cnblogs.com/yaocy/p/17072945.html

相关文章

  • 力扣 面试题 10.11. 峰与谷
    面试题10.11.峰与谷在一个整数数组中,“峰”是大于或等于相邻整数的元素,相应地,“谷”是小于或等于相邻整数的元素。例如,在数组{5,8,4,2,3,4,6}中,{8,6}是峰,{5,2}是谷。现在给定一个整数数组,将该数组按峰与谷的交替顺序排序。示例:输入:[5,3,1,2,3]输出: [......
  • COMP3331/9331 计算机网络与应用
    COMP3331/9331ComputerNetworksandApplicationsAssignmentforTerm1,2023Version1.0Due:11:59am(noon)Friday,21April2023(Week10)1.ChangeLogVersion1.0releasedon9thMarch2023.2.GoalandlearningobjectivesForthisassignment,youaretoimp......
  • jmeter模拟多IP地址访问
    1.前言:今天一同事在压测时提到怎么用jmeter里虚拟多个ip来发送请求,我想了一下以前用LR时用过虚拟ip地址,jmeter还没有使用过。想着原理应该是相通的,既然LR都能支持的话,那Jmeter应该也是支持,于是就有了jmeter虚拟化IP地址的研究。在网上也查找了相应的资料,摸索参考着实践了一把,坑吃......
  • jmeter模拟多IP地址访问
    1.前言:今天一同事在压测时提到怎么用jmeter里虚拟多个ip来发送请求,我想了一下以前用LR时用过虚拟ip地址,jmeter还没有使用过。想着原理应该是相通的,既然LR都能支持的话,那Jmeter应该也是支持,于是就有了jmeter虚拟化IP地址的研究。在网上也查找了相应的资料,摸索参考着实践了一把,坑吃......
  • codeforces 1793D Moscow Gorillas
    https://codeforces.com/contest/1793/problem/D解题思路依次找出MEX=1..n+1的序列数量就能得解。MEX=n+1只有全序列这一种情况。MEX=1时,找出两个序列中1的位置,较小位置左边的元素构成的子序列,较大位置右边的元素构成的子序列,以及两个位置中间的元素构成的子序列都满......
  • 力扣 376. 摆动序列
    376.摆动序列如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。例如, [1,7,4,9,2,5] 是一个 摆动序列 ,因为差值 (6,-3,5,-7,3) ......
  • 力扣626(MySQL)-换座位(中等)
    题目:表: Seat编写SQL查询来交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的id不交换。按 id 升序 返回结果表。查询结果格式如下所示。示例1: 解释:请注意,如果学生人数为奇数,则不需要更换最后一名学生的座位。解题思路:①交换座位号是交换相......
  • 力扣620(MySQL)-有趣的电影(简单)
    题目:某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个LED显示板做电影推荐,上面公布着影评和相关电影描述。作为该电影院的信息部主管,您需要编写一个SQL查询,找出所有影片描述为非 boring (不无聊) 的并且id为奇数 的影片,结果请按等级......
  • 力扣619(MySQL)-只出现一次的最大数字(简单)
    题目:MyNumbers 表:单一数字是在MyNumbers表中只出现一次的数字。请你编写一个SQL查询来报告最大的单一数字。如果不存在单一数字,查询需报告null。查询结果如下例所示。示例1: 示例2: 来源:力扣(LeetCode)链接:https://leetcode.cn/problems/biggest-single-num......
  • 力扣618(MySQL)-学生地理信息报告(困难)
    题目: 一所美国大学有来自亚洲、欧洲和美洲的学生,他们的地理信息存放在如下student表中该表没有主键。它可能包含重复的行。该表的每一行表示学生的名字和他们来自的大陆。一所学校有来自亚洲、欧洲和美洲的学生。示例:student: 写一个查询语句实现对大洲(continent)列的......