【问题标题】:Need to check if if number is aggregated number or not需要检查数字是否是聚合数字
【发布时间】:2015-11-22 03:34:28
【问题描述】:

如果该数字具有以下属性,则为数字“聚合数字”: 就像斐波那契数列 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;
   }
 }

【问题讨论】:

  • 111121325 - 11 + 1 = 12 怎么样; 1 + 12 = 13; 12 + 13 = 25,但你的程序返回 false
  • 感谢@BOND3,我刚刚测试了 3-4 个案例,有任何改进建议。

标签: java algorithm optimization


【解决方案1】:

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

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

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

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;
}

【讨论】:

    【解决方案2】:

    这是一个优化的版本,它不会重复解析数字,并且不使用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)的匹配。将两者都更改为 &lt; 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-02
      • 2018-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多