Java 从原始IP字符串计算所有有效IP地址

Java 从原始IP字符串计算所有有效IP地址,java,backtracking,Java,Backtracking,我现在正在解决leetcode问题93。还原IP地址 以下是url链接: 描述如下所示: 给定一个只包含数字的字符串s。返回可从s获取的所有可能的有效IP地址。你可以按任何顺序退货 一个有效的IP地址正好由四个整数组成,每个整数介于0和255之间,由单点分隔,并且不能有前导零。例如,“0.1.2.201”和“192.168.1.1”是有效的IP地址,“0.011.255.245”、“192.168.1.312”和“192”。168@1.1“是无效的IP地址 然而,当我试图通过回溯来解决问题时,我

我现在正在解决leetcode问题93。还原IP地址

以下是url链接:

描述如下所示: 给定一个只包含数字的字符串s。返回可从s获取的所有可能的有效IP地址。你可以按任何顺序退货

一个有效的IP地址正好由四个整数组成,每个整数介于0和255之间,由单点分隔,并且不能有前导零。例如,“0.1.2.201”和“192.168.1.1”是有效的IP地址,“0.011.255.245”、“192.168.1.312”和“192”。168@1.1“是无效的IP地址

然而,当我试图通过回溯来解决问题时,我无法找出总是返回空ArrayList的原因。我仔细检查了我的基本情况和递归,仍然找不到bug。任何帮助都将不胜感激,谢谢

public List<String> restoreIpAddresses(String s) {
        List<String> res = new ArrayList<>();
        if(s.length() == 0){
            return res;
        }
        int[] path = new int[4];
        snapshotIP(res,s,0,path,0);
        return res;
    }
    
    public void snapshotIP(List<String> res, String s, int index, int[] path, int segment){
        if(segment == 4 && index == s.length()){
            res.add(path[0]+"."+path[1]+"."+path[2]+"."+path[3]);
            return;
        }
        else if(segment == 4 || index == s.length()){
            return;
        }
        for(int len = 1; len <= 3 && index + len <= s.length(); len++){
            String snap = s.substring(index,index+len);
            int val = Integer.parseInt(snap);
            if(val > 225 || len >= 2 && s.charAt(index) == '0'){
                break;
            }
            path[segment] = val;
            snapshotIP(res,s,index+len,path,segment+1);
            path[segment] = -1; //undo the choice

        }
    }
public List restoreipaddress(字符串s){
List res=new ArrayList();
如果(s.length()==0){
返回res;
}
int[]路径=新的int[4];
快照IP(res,s,0,path,0);
返回res;
}
公共void快照IP(列表资源、字符串s、int索引、int[]路径、int段){
如果(段==4&&index==s.length()){
res.add(路径[0]+“+路径[1]+”+路径[2]+“+路径[3]);
返回;
}
else if(段==4 | |索引==s.length()){
返回;
}
对于(int len=1;len=2&&s.charAt(索引)='0'){
打破
}
路径[段]=val;
快照IP(res、s、索引+镜头、路径、段+1);
路径[段]=-1;//撤消选择
}
}

您的代码看起来不错,一点也不差,但不确定您的bug在哪里

这里有一个替代解决方案,虽然不太漂亮,但可以通过:

public final class Solution {
    public static final List<String> restoreIpAddresses(
        final String ip
    ) {
        List<String> res = new ArrayList<>();
        int length = ip.length();

        for (int i = 1; i < 4 && i < length - 2; i++)
            for (int j = i + 1; j < i + 4 && j < length - 1; j++)
                for (int k = j + 1; k < j + 4 && k < length; k++) {
                    final String part1 = ip.substring(0, i);
                    final String part2 = ip.substring(i, j);
                    final String part3 = ip.substring(j, k);
                    final String part4 = ip.substring(k, length);

                    if (isValid(part1) && isValid(part2) && isValid(part3) && isValid(part4)) {
                        res.add(part1 + "." + part2 + "." + part3 + "." + part4);
                    }
                }

        return res;

    }

    private static final boolean isValid(
        final String s
    ) {
        if (s.length() > 3 || s.length() == 0 || (s.charAt(0) == '0' && s.length() > 1) || Integer.parseInt(s) > 255) {
            return false;
        }

        return true;
    }
}
这是LeetCode的回溯深度优先搜索算法,它与您的类似,可能会帮助您找到答案

class Solution {
  int n;
  String s;
  LinkedList<String> segments = new LinkedList<String>();
  ArrayList<String> output = new ArrayList<String>();

  public boolean valid(String segment) {
    /*
    Check if the current segment is valid :
    1. less or equal to 255      
    2. the first character could be '0' 
    only if the segment is equal to '0'
    */
    int m = segment.length();
    if (m > 3)
      return false;
    return (segment.charAt(0) != '0') ? (Integer.valueOf(segment) <= 255) : (m == 1);
  }

  public void update_output(int curr_pos) {
    /*
    Append the current list of segments 
    to the list of solutions
    */
    String segment = s.substring(curr_pos + 1, n);
    if (valid(segment)) {
      segments.add(segment);
      output.add(String.join(".", segments));
      segments.removeLast();
    }
  }

  public void backtrack(int prev_pos, int dots) {
    /*
    prev_pos : the position of the previously placed dot
    dots : number of dots to place
    */
    // The current dot curr_pos could be placed 
    // in a range from prev_pos + 1 to prev_pos + 4.
    // The dot couldn't be placed 
    // after the last character in the string.
    int max_pos = Math.min(n - 1, prev_pos + 4);
    for (int curr_pos = prev_pos + 1; curr_pos < max_pos; curr_pos++) {
      String segment = s.substring(prev_pos + 1, curr_pos + 1);
      if (valid(segment)) {
        segments.add(segment);  // place dot
        if (dots - 1 == 0)      // if all 3 dots are placed
          update_output(curr_pos);  // add the solution to output
        else
          backtrack(curr_pos, dots - 1);  // continue to place dots
        segments.removeLast();  // remove the last placed dot 
      }
    }
  }

  public List<String> restoreIpAddresses(String s) {
    n = s.length();
    this.s = s;
    backtrack(-1, 3);
    return output;
  }
}
类解决方案{
int n;
字符串s;
LinkedList段=新建LinkedList();
ArrayList输出=新的ArrayList();
公共布尔值有效(字符串段){
/*
检查当前段是否有效:
1.小于或等于255
2.第一个字符可以是“0”
仅当段等于“0”时
*/
int m=段长度();
如果(m>3)
返回false;

return(segment.charAt(0)!='0')?(Integer.valueOf(segment)您已经编写了一个非常高级的代码。它适用于IP地址段低于225的所有情况,但第一个测试用例中有255个

修复非常简单,只需将“val>225”替换为“val>255”

应该是这样的:

if(val>255 | | len>=2&&s.charAt(index)='0')
附言。
我会采取不同的做法,我会在每个可能的地方添加点,并验证每个接收到的组合。

我花了时间添加单元测试并调试错误案例。除第一个之外,所有测试案例都从一开始就在工作:)
class Solution {
  int n;
  String s;
  LinkedList<String> segments = new LinkedList<String>();
  ArrayList<String> output = new ArrayList<String>();

  public boolean valid(String segment) {
    /*
    Check if the current segment is valid :
    1. less or equal to 255      
    2. the first character could be '0' 
    only if the segment is equal to '0'
    */
    int m = segment.length();
    if (m > 3)
      return false;
    return (segment.charAt(0) != '0') ? (Integer.valueOf(segment) <= 255) : (m == 1);
  }

  public void update_output(int curr_pos) {
    /*
    Append the current list of segments 
    to the list of solutions
    */
    String segment = s.substring(curr_pos + 1, n);
    if (valid(segment)) {
      segments.add(segment);
      output.add(String.join(".", segments));
      segments.removeLast();
    }
  }

  public void backtrack(int prev_pos, int dots) {
    /*
    prev_pos : the position of the previously placed dot
    dots : number of dots to place
    */
    // The current dot curr_pos could be placed 
    // in a range from prev_pos + 1 to prev_pos + 4.
    // The dot couldn't be placed 
    // after the last character in the string.
    int max_pos = Math.min(n - 1, prev_pos + 4);
    for (int curr_pos = prev_pos + 1; curr_pos < max_pos; curr_pos++) {
      String segment = s.substring(prev_pos + 1, curr_pos + 1);
      if (valid(segment)) {
        segments.add(segment);  // place dot
        if (dots - 1 == 0)      // if all 3 dots are placed
          update_output(curr_pos);  // add the solution to output
        else
          backtrack(curr_pos, dots - 1);  // continue to place dots
        segments.removeLast();  // remove the last placed dot 
      }
    }
  }

  public List<String> restoreIpAddresses(String s) {
    n = s.length();
    this.s = s;
    backtrack(-1, 3);
    return output;
  }
}