Go Java算法之累加数示例详解

Go Java算法之累加数示例详解

什么是累加数

累加数是指一个字符串序列,划分成多个数字序列,每个数字序列的数字之和等于后面的数字序列的第一个数字。

例如:112358 是一个累加数,因为 1+1=2, 1+2=3, 2+3=5, 3+5=8,后面的数字序列分别为 1, 2, 3, 5。

算法思路

为了判断一个字符串是否为累加数,我们需要枚举前两个数字,然后依次判断后面的数字序列是否合法即可。

假设第一个数字为 i,第二个数字为 j,那么第三个数字就是 i+j,接下来用 i+j 对原字符串进行截取,判断剩余的字符串是否为 i+j,以此类推。

注意,数字序列不能以 0 开头,所以 i 和 j 可能是一位数、两位数、三位数中的任意两个数字。

示例说明

下面给出两个示例,来详细解释累加数的判断过程。

示例一

输入的字符串为 "11235813"。

我们首先枚举前两个数字:i=1, j=1。

然后计算出第三个数字,即 i+j=2,将字符串从当前位置截取出来,得到 "235813",判断该字符串是否为 2,发现不是,因此这个枚举的结果不合法。

接下来我们枚举下一组:i=1, j=2。

计算出第三个数字 i+j=3,截取字符串得到 "35813",判断该字符串是否为 3,不是。

接下来继续枚举:i=2, j=3。

计算出第三个数字 i+j=5,截取字符串得到 "5813",判断该字符串是否为 5,不是。

接下来继续枚举:i=3, j=5。

计算出第三个数字 i+j=8,截取字符串得到 "13",判断该字符串是否为 8,不是。

接下来继续枚举:i=5, j=8。

计算出第三个数字 i+j=13,截取字符串得到 "",判断该字符串是否为 13,是。

因此,该字符串是一个累加数。

示例二

输入的字符串为 "199100199"。

我们首先枚举前两个数字:i=1, j=9。

然后计算出第三个数字,即 i+j=10,由于下一位是 9,因此第一部分为 "19"。

依次计算出第四个数字:i+j=19,截取字符串得到 "9100199",发现它不等于 19,因此这个枚举的结果不合法。

接下来继续枚举:i=9, j=1。

计算出第三个数字 i+j=10,由于第二部分以 0 开头,不合法。

接下来继续枚举:i=1, j=9。

计算出第三个数字 i+j=10,第一部分为 "19",第二部分为 "9"。

依次计算出第四个数字:i+j=19,截取字符串得到 "100199",不等于 19。

接下来继续枚举:i=9, j=1。

计算出第三个数字 i+j=10,第一部分为 "199",第二部分为 "1"。

依次计算出第四个数字:i+j=11,截取字符串得到 "00199",不等于 11。

接下来继续枚举:i=1, j=9。

计算出第三个数字 i+j=10,第一部分为 "1",第二部分为 "99100199"。

依次计算出第四个数字:i+j=9,截取字符串得到 "9100199",不等于 9。

接下来继续枚举:i=9, j=9。

由于第一个数字不能为 0,因此这个枚举的结果不合法。

因此,该字符串不是一个累加数。

代码实现

下面给出代码实现的主要部分,具体实现细节请参考代码注释。

func isAdditiveNumber(num string) bool {
    n := len(num)
    for i := 1; i <= n/2; i++ { // 枚举第一个数字的长度
        for j := 1; j <= (n-i)/2; j++ { // 枚举第二个数字的长度
            if check(num[:i], num[i:i+j], num[i+j:]) { // 如果找到了一个累加数直接返回 true
                return true
            }
            // 如果第二个数字以 0 开头,则不能继续往下枚举
            if num[i:i+j][0] == '0' {
                break
            }
        }
        // 如果第一个数字以 0 开头,则不能继续往下枚举
        if num[0] == '0' {
            break
        }
    }
    return false
}

// 判断是否为累加数
func check(s1, s2, s3 string) bool {
    for len(s3) > 0 { // 按照累加数的定义依次判断后面的数字序列
        if !strings.HasPrefix(s3, add(s1, s2)) {
            return false
        }
        s1, s2, s3 = s2, add(s1, s2), s3[len(add(s1, s2)):]
    }
    return true
}

// 计算两个字符串数字的和
func add(s1, s2 string) string {
    i, j, carry, sum := len(s1)-1, len(s2)-1, 0, []byte{}
    for i >= 0 || j >= 0 {
        n1, n2 := 0, 0
        if i >= 0 {
            n1 = int(s1[i] - '0')
            i--
        }
        if j >= 0 {
            n2 = int(s2[j] - '0')
            j--
        }
        tmp := n1 + n2 + carry
        sum = append(sum, byte(tmp%10)+'0')
        carry = tmp / 10
    }
    if carry > 0 {
        sum = append(sum, byte(carry)+'0')
    }
    // 由于我们计算结果时是从低位开始的,因此要将结果翻转一下
    for i, n := 0, len(sum); i < n/2; i++ {
        sum[i], sum[n-i-1] = sum[n-i-1], sum[i]
    }
    return string(sum)
}

总结

累加数问题实际上可以转化为一个回溯问题,但是优化后的暴力枚举已经足够应对该问题。在实现时需要注意细节,例如数字序列不能以 0 开头、要注意截取字符串的范围等等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Go Java算法之累加数示例详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • JSP中动态include与静态include的区别介绍

    JSP中的include指令可以用来在页面中包含其它页面或文件,包括动态包含与静态包含两种方式。下面我们来详细讲解一下它们的区别。 动态include 动态include是最常用的一种方式,可以根据条件动态包含不同的页面。它是通过JSP中的include指令和JSP脚本语言实现的。 基本语法 <jsp:include page="filena…

    Java 2023年6月15日
    00
  • Spring Security常用过滤器实例解析

    接下来我将为您详细讲解 Spring Security 常用过滤器实例解析的完整攻略。 1. Spring Security 常用过滤器简介 Spring Security 是一种强大且高度可定制的认证和授权框架,它为 Web 应用程序提供了安全性。Spring Security 通过使用一系列过滤器来保护应用程序,并控制对资源的认证和授权访问。Spring…

    Java 2023年5月20日
    00
  • JDK9对String字符串的新一轮优化

    本次讲解将从以下几个方面详细讲解JDK9对String字符串的新一轮优化: 1.记录String字符串的byte数组2.String字符串的实现方式升级到Compact String3.使用try-with-resources自动关闭资源4.String的重复操作5.示例说明 1. 记录String字符串的byte数组 在JDK9中,String字符串可以记…

    Java 2023年5月27日
    00
  • Mybatis之@ResultMap,@Results,@Result注解的使用

    Mybatis是一款优秀的ORM框架,它提供了丰富的注解来进行对象和数据库的映射。其中@ResultMap、@Results、@Result三个注解是使用频率较高的几个。下面将详细讲解它们的使用方法及示例。 一、@ResultMap注解的使用 @ResultMap注解用于引用一个已经定义好的resultMap,在查询时用作查询结果集的映射。resultMap…

    Java 2023年5月20日
    00
  • 详解JDK自带javap命令反编译class文件和Jad反编译class文件(推荐使用jad)

    详解JDK自带javap命令反编译class文件和Jad反编译class文件 什么是javap命令和Jad反编译? javap命令是JDK自带的反编译工具,用于反编译class文件。 Jad是一款免费的Java反编译器,可以将class文件反编译为Java源代码。 使用javap命令反编译class文件 打开命令行工具,进入.class文件所在的目录。 键入…

    Java 2023年5月19日
    00
  • java的Hibernate框架报错“NonUniqueObjectException”的原因和解决方法

    当使用Hibernate框架时,可能会遇到“NonUniqueObjectException”错误。这个错误通常是由于以下原因之一引起的: 多个实体对象具有相同的标识符:如果您的多个实体对象具有相同的标识符,则可能会出现此错误。在这种情况下,需要检查您的实体对象并确保它们具有唯一的标识符。 会话中存在多个实体对象:如果您的会话中存在多个实体对象,则可能会出现…

    Java 2023年5月4日
    00
  • Tomcat中使用ipv6地址的示例代码

    下面是Tomcat中使用IPv6地址的示例代码的攻略: 确认Tomcat版本 首先需要确认Tomcat的版本,因为不同版本的Tomcat对IPv6的支持可能会有所不同。确保使用的Tomcat版本是7.0或更高版本,这些版本都支持IPv6地址。 配置server.xml 编辑Tomcat的配置文件server.xml,在 <Connector> 元…

    Java 2023年5月19日
    00
  • Java实现万年历效果

    下面是“Java实现万年历效果”的完整攻略。 准备工作 在实现万年历之前,需要先了解一些基本知识: Java 的日期类 Date、Calendar 和 LocalDate Java 的输入输出流,包括 Scanner 和 System.out Java 的字符串拼接和格式化输出 模块化编程及测试方法 实现步骤 接下来就可以开始实现万年历了。 步骤1:获取用户…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部