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, 0
var 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') { //求numA
continue
}
tt := numA
for j := i + 1; j <= len(num); j++ {
if numB, err = strconv.Atoi(num[i:j]); err != nil || (j != i+1 && num[i] == '0') {//求numB
continue
}
numA, lenA, lenB = tt, i-0, j-i
lenC = 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,直接break
break
}
lenC = end - start
if !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 + 1
end = 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
}