需要检查数字是否为汇总数字

时间:2015-11-22 03:34:28

标签: java algorithm optimization

数字"汇总数字"如果此号码具有以下属性: 就像斐波那契数字一样 1,1,2,3,5,8,13 .....

数字中的数字可以分成几个部分,后面的部分是前面部分的总和。

喜欢

112358, because 1+1=2, 1+2=3, 2+3=5, 3+5=8
122436 because 12+24=36
1299111210, because 12+99=111, 99+111=210
112112224, because 112+112=224

需要提供一个函数来检查这个数字是否是聚合数字?

我编写代码但需要对其进行优化。请帮忙

public class AggragetedNumber {
  public static void main(String[] args) {
    System.out.println(isAggregatedNumber("1121325"));
}

static boolean isAggregatedNumber(String text) {
    int length = text.length() / 2;
    for (int i = 1; i <= length; i++) {
        for (int j = 2; j <= length; j++) {
            if (Match(i, j, text)) {
                return true;
            }
        }
    }
    return false;
}

static boolean Match(int i, int j, String text) {
    String first = text.substring(0, i);
    String second = text.substring(i, i * 2);
    StringBuilder buffer = new StringBuilder(first);
    buffer.append(second);
    while (buffer.length() < text.length()) {
        Integer x = (Integer.parseInt(first) + Integer.parseInt(second));
        String third = x.toString();
        buffer.append(third);
        first = second;
        second = third;
    }
    if (text.equals(buffer.toString()))
        return true;
    return false;
   }
 }

2 个答案:

答案 0 :(得分:1)

我认为关键是要检查前两个数字的正确排列:

1)第一个数字的长度不应超过整个数字长度的一半

2)第一个&amp;的长度第二个数字不应超过整个数字的长度减去第一个数字或第二个数字的长度,以较大者为准(尽管可以进一步优化)

public static void main(String[] args) {
    System.out.println(isAggregatedNumber("111121325"));// true
    System.out.println(isAggregatedNumber("122436"));// true
    System.out.println(isAggregatedNumber("122437"));// false
    System.out.println(isAggregatedNumber("1299111210"));// true
    System.out.println(isAggregatedNumber("112112224"));// true
    System.out.println(isAggregatedNumber("112012224"));// false
}

static boolean isAggregatedNumber(String text) {
    int length = text.length();
    for (int i = 1; i <= length / 2; i++) { // length of the first number should not exceed half of the length of the entire number
        for (int j = i + 1; j <= length - Math.max(i, j - i); j++) { // length of the first & second number should not exceed length of the entire number minus length of the first number or the second, whichever is bigger
            if (Match(i, j, text)) {
                return true;
            }
        }
    }
    return false;
}

static boolean Match(int i, int j, String text) {
    String first = text.substring(0, i);
    String second = text.substring(i, j);
    StringBuilder buffer = new StringBuilder(first);
    buffer.append(second);
    while (buffer.length() < text.length()) {
        Integer x = (Integer.parseInt(first) + Integer.parseInt(second));
        String third = x.toString();
        buffer.append(third);
        first = second;
        second = third;
    }
    if (text.equals(buffer.toString()))
        return true;
    return false;
}

答案 1 :(得分:0)

这是一个优化版本,不会反复解析数字,也不会使用StringBuilder,这会使错误更快地失败:

private static boolean isAggregatedNumber(String text) {
    for (int len1 = 1; len1 <= text.length() / 2; len1++) {
        int num1 = Integer.parseInt(text.substring(0, len1));
        for (int end2 = len1 + 1; end2 <= text.length() - len1; end2++) {
            int num2 = Integer.parseInt(text.substring(len1, end2));
            if (isAggregatedNumber(text, end2, num1, num2))
                return true;
        }
    }
    return false;
}
private static boolean isAggregatedNumber(String text, int start, int num1, int num2) {
    for (;;) {
        final int    num3 = num1 + num2;
        final String str3 = Integer.toString(num3);
        final int    end3 = start + str3.length();
        if (end3 > text.length())
            return false;
        if (! text.substring(start, end3).equals(str3))
            return false;
        if (end3 == text.length())
            return true;
        start = end3;
        num1 = num2;
        num2 = num3;
    }
}

如果您愿意,可以使用尾递归:

private static boolean isAggregatedNumber(String text, int start, int num1, int num2) {
    final int    num3 = num1 + num2;
    final String str3 = Integer.toString(num3);
    final int    end3 = start + str3.length();
    if (end3 > text.length() || ! text.substring(start, end3).equals(str3))
        return false;
    if (end3 == text.length())
        return true;
    return isAggregatedNumber(text, end3, num2, num3);
}

使用扩展测试用例进行测试:

public static void main(String[] args) {
    System.out.println(isAggregatedNumber("00000000000000000"));   // true: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    System.out.println(isAggregatedNumber("112"));                 // true: 1,1,2
    System.out.println(isAggregatedNumber("113"));                 // false: 1,1,3
    System.out.println(isAggregatedNumber("122436"));              // true: 12,24,36
    System.out.println(isAggregatedNumber("122437"));              // false: 12,24,37
    System.out.println(isAggregatedNumber("1123581321345589144")); // true: 1,1,2,3,5,8,13,21,34,55,89,144 (fibonacci)
    System.out.println(isAggregatedNumber("5611"));                // true: 5,6,11
    System.out.println(isAggregatedNumber("1121325"));             // true: 1,12,13,25 
    System.out.println(isAggregatedNumber("111121325"));           // true: 11,1,12,13,25
    System.out.println(isAggregatedNumber("1299111210"));          // true: 12,99,111,210
    System.out.println(isAggregatedNumber("11234512346"));         // true: 1,12345,12346
    System.out.println(isAggregatedNumber("12345112346"));         // true: 12345,1,12346
    System.out.println(isAggregatedNumber("112112224"));           // true: 112,112,224
    System.out.println(isAggregatedNumber("112012224"));           // false
}

<强> 警告

第一种方法中两个for循环的循环优化会阻止000100000340001,000003,4又名1,3,4)的匹配。将两者都更改为< text.length(),以便支持前两个数字中的前导零。

更好的是,使用以下方法防范前导零:

private static boolean isAggregatedNumber(String text) {
    for (int len1 = 1; len1 < text.length() - 1; len1++) {
        int num1 = Integer.parseInt(text.substring(0, len1));
        for (int end2 = len1 + 1; end2 < text.length(); end2++) {
            int num2 = Integer.parseInt(text.substring(len1, end2));
            if (isAggregatedNumber(text, end2, num1, num2))
                return true;
            if (text.charAt(len1) == '0')
                break;
        }
        if (text.charAt(0) == '0')
            break;
    }
    return false;
}