【LeetCode每日一题】——93.复原IP地址

一【题目类别】

  • 字符串

二【题目难度】

  • 中等

三【题目编号】

  • 93.复原IP地址

四【题目描述】

  • 给定一个只包含数字的字符串,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。
  • 有效 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 地址。

五【题目示例】

  • 示例 1:
    输入:s = “25525511135”
    输出:[“255.255.11.135”,“255.255.111.35”]
  • 示例 2:
    输入:s = “0000”
    输出:[“0.0.0.0”]
  • 示例 3:
    输入:s = “1111”
    输出:[“1.1.1.1”]
  • 示例 4:
    输入:s = “010010”
    输出:[“0.10.0.10”,“0.100.1.0”]
  • 示例 5:
    输入:s = “101023”
    输出:[“1.0.10.23”,“1.0.102.3”,“10.1.0.23”,“10.10.2.3”,“101.0.2.3”]

六【题目提示】

  • 0 <= s.length <= 3000
  • s 仅由数字组成

七【解题思路】

  • 深度优先搜索+剪枝回溯,具体步骤如下:
  1. 每次递归判断是否找到了一组,如果找到了一组,再判断是否全部使用,如果全部数字都使用了,加入即可,如果还有剩余数字没有使用,剪枝回溯
  2. 因为每位最少一个数字,最多三个数字,所以从1到3截取,也就是每组多少个数字,当前要判断截取的数字是否可用,还要判断截取是否越位
  3. 截取到一个合理的加入到数组中,开始递归下一位
  4. 最后剪枝回溯

八【时间频度】

  • 时间复杂度:时间复杂度由递归树的层数决定,一般是常数级别 O ( N ) O(N) O(N)

九【代码实现】

  1. Java语言版
package String;

import java.util.ArrayList;
import java.util.List;

public class p93_RestoreIpAddresses {

    public static void main(String[] args) {
        String s = "25525511135";
        List<String> res = restoreIpAddresses(s);
        System.out.println("res = " + res);
    }

    public static List<String> restoreIpAddresses(String s) {
        List<String> res = new ArrayList<>();
        if (s == null || s.length() == 0) {
            return res;
        }
        backTrack(s, 0, new ArrayList<>(), res);
        return res;
    }

    /**
     * 进行回溯判断
     *
     * @param s   要判断的字符串
     * @param pos 当前遍历到s字符串中的位置
     * @param cur 当前存放已经确定好的ip段的数量
     * @param res 返回结果
     */
    public static void backTrack(String s, int pos, List<String> cur, List<String> res) {
        // 首先进行判断,如果已经分成了四分,那么判断里面的内容是否符合要求
        if (cur.size() == 4) {
            // 继续判断,如果pos已经到了s的最后,说明所有的字符已经遍历完毕
            if (pos == s.length()) {
                // 那么就将这一个符合要求的加入到结果数组
                res.add(String.join(".", cur));
            }
            return;
        }

        // 因为每位地址是三位数,所以需要考虑到每一位的情况,需要遍历3次
        for (int i = 1; i <= 3; i++) {
            // 如果当前位置距离s末尾小于3就不用继续分段了,因为就剩两个了,直接跳出这次循环
            if (pos + i > s.length()) {
                break;
            }
            // 开始分段,一个一个分段,从每位地址的第一位到第三位
            String segment = s.substring(pos, pos + i);
            // 判断分段的数是否符合要求,首先起始位置不能为零,并且分段的长度不能大于1,且int类型不能大于255
            if (segment.startsWith("0") && segment.length() > 1 || (i == 3) && Integer.parseInt(segment) > 255) {
                continue;
            }
            // 将符合要求的加入到cur数组中
            cur.add(segment);
            // 继续遍历下一个位置
            backTrack(s, pos + i, cur, res);
            // 如果进行到这里,说明还没结束整个循环,那么回溯到上一个元素,继续进行判断,删除最后一个元素
            cur.remove(cur.size() - 1);
        }
    }

}
  1. C语言版
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>

#define MAX_SIZE 1024 /*结果数组的最大长度*/

/*判断当前截取的是否可用*/
bool isValid(char *s, int len)
{
	if (s == '\0')
	{
		return false;
	}
	if (s[0] == '0' && len > 1)
	{
		return false;
	}
	int num = 0;
	for (int i = 0; i < len; i++)
	{
		num = num * 10 + s[i] - '0';
	}
	if (num >= 0 && num <= 255)
	{
		return true;
	}
	return false;
}

/*使用深度优先遍历*/
void dfs(char *s, char **res, int *returnSize, char *str, int idx, int validNum)
{
	if (validNum > 4)
	{
		return;
	}
	if (s[0] == '\0' && validNum == 4)
	{
		res[*returnSize] = (char *)malloc(strlen(str) + 1);
		strcpy(res[*returnSize], str);
		(*returnSize)++;
	}
	if (validNum > 0 && validNum < 4)
	{
		str[idx++] = '.';
	}
	for (int len = 1; len <= 3 && len <= strlen(s); len++)
	{
		if (isValid(s, len))
		{
			for (int i = 0; i < len; i++)
			{
				str[idx + 1] = s[i];
			}
			dfs(s + len, res, returnSize, str, idx + len, validNum + 1);
		}
	}
}

/*操作另外两个函数*/
char ** restoreIpAddresses(char * s, int* returnSize)
{
	char **res = (char **)malloc(MAX_SIZE * sizeof(char *));
	*returnSize = 0;
	char *str = (char *)calloc(strlen(s) + 4, sizeof(char));
	dfs(s, res, returnSize, str, 0, 0);
	return res;
}

/*主函数省略*/

十【提交结果】

  1. Java语言版
    在这里插入图片描述
  2. C语言版
    在这里插入图片描述
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IronmanJay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值