数字转换为合法IP地址

算法题目:
给定一串数字, 返回所有合法的ipv4地址集合。
例如: 给出数字12345, 返回1.2.3.45、1.2.34.5、1.23.4.5等等。

思路:
ip地址是*...*格式。 每个ip段合法值是0~255, 即合法的ip地址格式应该是[0,255].[0,255].[0,255].[0,255]。 可以通过递归实现, 顺序遍历数字添加数字到当前ip段或者下一段, 当数字遍历到末尾且存在4个ip段则找到了合法的地址。

边界条件:
1、ip段位空, 添加当前数字到第一段;
2、每次获取最后一个ip段, 判断当前数字和ip段相加是否超过255。 如果超过255, 则只能将当前数字添加到下一个ip段; 如果小于255, 则当前数字可以添加到最后一个ip段或者下一个ip段;
3、遍历的下标超过字符串长度或者ip段长度超过4;

public class NumberToIp {

  public static void main(String[] args) {
    List<String> ret1 = convertNumberToIp(1000L);

    List<String> ret2 = convertNumberToIp(123455L);
    List<String> ret3 = convertNumberToIp(2343355L);

    // 返回空数组, 没有合法ipv4地址
    List<String> ret4 = convertNumberToIp(234573363323L);

    System.out.println("result");
  }

  /**
   * 返回数字对应的ip v4地址所有可能结果,
   * 例如123456, 返回如下合法地址
   * 123.4.5.6
   * 12.3.4.56
   * 1.23.4.56
   * 1.2.34.56
   * @param number
   * @return
   */
  public static List<String> convertNumberToIp(long number) {
    if (number < 1000L) {
      return null;
    }

    // 结果, 每个元素是合法的ip地址
    List<String> ipList = new ArrayList<>();

    String strNumber = String.valueOf(number);

    // 缓存中间结果
    List<String> tpmSections = new ArrayList<>(4);

    // 递归每一位数字
    recurseCalculateIp(ipList, tpmSections, strNumber, 0);

    return ipList;
  }

  /**
   * 递归判断
   * @param result, 合法ip地址
   * @param tmpList, 中间结果, 最多4个元素。 每个元素值在0~255之间
   * @param strNumber, 输入的数字
   * @param currentPosition 当前遍历到第几位
   */
  private static void recurseCalculateIp(List<String> result, List<String> tmpList,
      String strNumber, int currentPosition) {
    // 合法ip
    if (currentPosition == strNumber.length()
        && tmpList.size() == 4) {
      StringBuilder builder = new StringBuilder();
      for (int i = 0; i < 4; i++) {
        builder.append(tmpList.get(i));
        if (i != 3) {
          builder.append(".");
        }
      }
      result.add(builder.toString());

      return;
    }

    if (currentPosition >= strNumber.length()
      || tmpList.size() > 4) {
      // 非法数据
      return;
    }

    int curNumber = strNumber.charAt(currentPosition) - '0';

    if (tmpList.size() == 0) {
      // 当前是空数组
      List<String> bufList1 = new ArrayList<>();
      bufList1.add(String.valueOf(curNumber));
      recurseCalculateIp(result, bufList1, strNumber, currentPosition + 1);
    } else {
      String lastSection = tmpList.get(tmpList.size() - 1);
      int sectionValue = Integer.parseInt(lastSection);

      if (sectionValue * 10 + curNumber > 255) {
        // 最后一段ip加上当前值超过255, 添加到下一个section
        List<String> tmp1 = new ArrayList<>();
        tmp1.addAll(tmpList);
        tmp1.add(String.valueOf(curNumber));
        recurseCalculateIp(result, tmp1, strNumber, currentPosition + 1);
      } else {
        // 比如当前端是12, 可以补充第3位; 也可以将当前数字放到下一个ip段
        List<String> tmp1 = new ArrayList<>();
        List<String> tmp2 = new ArrayList<>();
        for (String str:tmpList) {
          tmp1.add(str);
          tmp2.add(str);
        }

        // 最后的ip段是12, 添加当前数字到下一个ip段
        tmp1.add(String.valueOf(curNumber));
        recurseCalculateIp(result, tmp1, strNumber, currentPosition + 1);

        // 最后的ip段是12, 更改为123
        tmp2.remove(tmp2.size() - 1);
        tmp2.add(String.valueOf(sectionValue * 10 + curNumber));
        recurseCalculateIp(result, tmp2, strNumber, currentPosition + 1);
      }
    }
  }
}

版权声明:本文为brycegao321原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。