[力扣每日一鸡]——93.复原IP地址(详解)

算法思想转自力扣题解diocletian(作者),仅用于个人学习

复原IP地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 ‘.’ 分隔。
示例:

输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]

题解:
题目中需要使用string类中的substr函数来截取字符串:substr是C++语言函数,主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。
问题的有一个坑:数字0是否出现在IP地址首,如果出现那么这个IP地址失效。
使用回溯法穷举(有点暴力破解的意思,时间复杂程度为O(n^4)),并不进行总位数的判断。
思路很简单:穷举并判断,在开始的时候我们不需要关注他有多少位第一个点前面应该有几位数,因为数字最多是三位,所以首先取2、25、255,首先进行第一个数字的判断,2满足0<2<255,加点然后从5开始,又分为三种情况5、55、552,后面处理和之前相同。
采用递归实现,递归返回条件有三:
1、点的数量达到4个(因为最后一组数的后面还会加一个点,在放入容器之前会去掉),但是没有到达字符串末尾,此方案失败。
2、点的数量没有达到4个,但是到达字符串末尾,此方案失败。
3、点的数量到达四个,同时到达字符串末尾,此方案成功,入容器。

class Solution {
	vector<string> ans;//存放最终结果
	int n;//要修复字符串的长度
	string result;//表示回溯中当前已经拼起来的字符串
	int num_dot;//result中点的个数
	int idx;//用来表示当前已经截取到s的位置
public:
	//判断当前数字是否在合法范围内0~255
	bool check(string x)
	{
		int m = stoi(x);
		return m >= 0 && m <= 255;
	}

	void backtrack(string& s)
	{
		//递归终止条件
		if (num_dot == 4 && idx >= n)
		{//如果刚好凑齐4个“.”号,而且s遍历完毕。result删掉最后一个点号后加入答案。
			ans.push_back(result.substr(0, result.size() - 1));
			return;
		}

		//否则如果遍历完了,也没凑齐4个".",说明不能构成合法IP
		else if (idx >= n && num_dot < 4)return;
		//或者没有遍历完,但已经超过4个"."了,不能构成合法IP
		else if (idx <= n - 1 && num_dot >= 4)return;

		//否则,可以继续往result后面加1位,2位或者3位。需要考虑2个问题:有没有这么多位,以及是不是0开头
		vector<string> strs;//result后面能加哪些
		for (int i = 0; i < 3 && idx + i < n;++i)
		{//第i个候选者,长度为i+1
			string candidate = s.substr(idx, i + 1);
			//注意如果长度为2或者3的时候,第1位不能为0.
			if (i != 0 && candidate[0] == '0')continue;
			//否则加入strs中
			strs.push_back(candidate);
		}

		//对strs里面每一种可行方案,遍历,回溯
		for (int i = 0;i < strs.size();++i)
		{
			if (check(strs[i]))//判断数字是否合法
			{
				//判断传入的字符串长度
				int len = strs[i].size();
				//将字符串与result进行拼接并且在后面加点
				result += (strs[i] + ".");
				//点个数加1
				num_dot++;
				//已经截取s位置的下一个位置,即还未截取的第一个位置
				idx += len;
				//递归,将后面还未截取的重新截取
				backtrack(s);
				//重置result,num_dot,idx,准备迎接下一个strs[i]
				result = result.substr(0, result.size() - len - 1);
				num_dot--;
				idx -= len;
			}
		}
		return;
	}

	vector<string> restoreIpAddresses(string s) {
		//初始化
		ans.clear();
		n = s.size();
		idx = 0;//已汲取s的长度
		num_dot = 0;//点的个数 
		result = "";//回溯过程中拼好的字符串

		backtrack(s);

		return ans;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值