306. 累加数
题目描述:
累加数 是一个字符串,组成它的数字可以形成累加序列。
一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,序列中的每个后续数字必须是它之前两个数字之和。
给你一个只包含数字 ‘0’-‘9’ 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false 。
说明:累加序列里的数,除数字 0 之外,不会 以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。
考察重点:判断一个字符串是否符合前两个之和为第三个数 F(n)=F(n - 1)+F(n - 2)。我们使用go语言中的strconv是否报错来判断数字是否越界;之后只需确定起始的两个数字A,B,并找到是否存在C=A+B,如果没有则跳出(使用A,B两数的位数确定C的位数在max(A,B)与max(A,B)+1之间
);有则执行A=B,B=C,继续向后遍历。
func isLegal(a, b, c int) bool {return c-a == b
}
func max1(a, b int) int {if a > b {return a}return b
}
func IsAdditiveNumber(num string) bool {numA, numB, numC, lenA, lenB, lenC := 0, 0, 0, 0, 0, 0var err error/**本题最关键是找到前两个数,用num[0:i]和num[i:j+1]分别表示前两个数lenA, lenB记录这两个数长度,则numC的长度lenC必然等于max(lenA,lenB)或者max(lenA,lenB)+1*/for i := 1; i <= len(num); i++ {if numA, err = strconv.Atoi(num[0:i]); err != nil || (i != 1 && num[0] == '0') { //求numAcontinue}tt := numAfor j := i + 1; j <= len(num); j++ {if numB, err = strconv.Atoi(num[i:j]); err != nil || (j != i+1 && num[i] == '0') {//求numBcontinue}numA, lenA, lenB = tt, i-0, j-ilenC = max1(lenA, lenB)start, end := j, j+lenC //记录numA,numB的长度,同时numC只可能在num[j:j+max(lenA,lenB)] 与 num[j:j+max(lenA,lenB)+1] 之中for end <= len(num) { //**********************************************************************************************************if numC, err = strconv.Atoi(num[start:end]); err != nil || (end != start+1 && num[start] == '0') { //如果num[start:end]大于MAXINT,直接breakbreak}lenC = end - startif !isLegal(numA, numB, numC) { //num[start:end]!=numA+numB 则继续判断num[start:end+1]if end+1 > len(num) {break}if numC, err = strconv.Atoi(num[start : end+1]); err != nil || (end+1 != start+1 && num[start] == '0') {break}if !isLegal(numA, numB, numC) {break}lenC = lenC + 1end = end + 1 //num[start:end+1]==numA+numB 则更新lenC和end的大小}//**********************************************************************************************************if end == len(num) { //end等于len(num)且num[start:end]==numA+numB,说明该string满足条件return true}numA, numB, lenA, lenB = numB, numC, lenB, lenC //numA,numB整体向后,lenC,start,end重新记录新的numC可能的取值范围lenC = max1(lenA, lenB)start, end = end, end+lenC}}}return false
}