leetcode306. 累加数

  • https://leetcode.com/problems/additive-number/

  • 累加数 是一个字符串,组成它的数字可以形成累加序列。

  • 一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,序列中的每个后续数字必须是它之前两个数字之和。

  • 给你一个只包含数字 ‘0’-‘9’ 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false 。

  • 说明:累加序列里的数,除数字 0 之外,不会 以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。

示例 1:

输入:"112358"
输出:true 
解释:累加序列为: 1, 1, 2, 3, 5, 81 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8
示例 2:

输入:"199100199"
输出:true 
解释:累加序列为: 1, 99, 100, 1991 + 99 = 100, 99 + 100 = 199

1 <= num.length <= 35
num 仅由数字(0 - 9)组成

题解

  • 使用两个分割的指针分割,然后使用函数判断分割后的字符串能否满足要求。
  • 还需注意字符串的操作超过int(4byte = 4*8 =32二进制)的范围。

暴力循环:add string处理数值操作

class Solution {
public:
    // 大数加法模板
    string add(string& a,string& b){
        int n1 = a.size()-1;
        int n2 = b.size()-1;
        int carry = 0; //进位符号
        string ans;

        while(n1>=0||n2>=0||carry>0){
            int t1=n1>=0?a[n1--]-'0':0;
            int t2=n2>=0?b[n2--]-'0':0;
            ans+=(t1+t2+carry)%10+'0';
            carry=(t1+t2+carry)/10;
        }

        reverse(ans.begin(),ans.end());
        return ans;
    }

	//判断分割后的字符串是否满足题意
    // num1: [i, j) + num2: [j, k) = sum: [k, ..)
    bool valid(string& num, int i, int j, int k) {
        if (num[i] == '0' && j != i+1) return false;
        if (num[j] == '0' && k != j+1) return false;

        string a = num.substr(i, j-i);
        string b = num.substr(j, k-j);

        string sum = add(a, b);
        if (sum.size() + k > num.size()) return false;


        for (int s = 0; s <= sum.size() - 1; s++) {
            if (sum[s] != num[s+k]) return false;
        }
        if (sum.size() + k == num.size()) return true;

        return valid(num, j, k, sum.size()+k);
    }

    bool isAdditiveNumber(string num) {
        for (int i = 1; i < num.size(); i++) {
            for (int j = i+1; j < num.size(); j++) {
                if (valid(num, 0, i, j)) return true;
            }
        }
        return false;
    }
};


// 链接:https://leetcode.cn/problems/additive-number/solution/wei-rao-li-lun-da-shu-jia-fa-hui-su-yan-9q0d5/

暴力循环: long long int处理数值操作

class Solution {
private:
    long long int getNum(const string num, int pos, int len) {      //字符串转ll数字,如果非法返回-1;
        if (pos != 0 and len != 1 and num[pos] == '0')
            return -1;
        return stoll(num.substr(pos, len), NULL, 10);
    }
public:
    bool isAdditiveNumber(string num) {
        if (num.size() < 3)    return 0;
        int a_len = 1;
        bool a_f = true;
        while (a_len <= floor(num.size() / 2) and a_f) {
            int a_pos = 0; //第一个数a总是从0位置开始的
            int b_pos = a_pos + a_len; //第二个数的开始位置
            int b_len = 1;
            bool b_f = true;
            while (b_len <= floor((num.size() - a_len) / 2) and a_f and b_f) {
                int c_pos = b_pos + b_len; //第三个数的开始位置
                int c_len = max(a_len, b_len);//第三个数的起始长度
				bool c_f = true;
                long long int a = getNum(num, a_pos, a_len);
                if (a == -1) {
                    a_f = false;
                    break;
                }
                long long int b = getNum(num, b_pos, b_len);
                if (b == -1) {
                    b_f = false;
                    break;
                }
                int a_len_temp = a_len;
                int b_len_temp = b_len;
				while (c_pos + c_len <= num.size()) {
					if (c_len > (max(a_len_temp, b_len_temp) + 1) and c_f) 
						break;
					long long int c = getNum(num, c_pos, c_len);
					if (c == -1) {
						c_f = false;
						break;
					}
					if (a + b == c) {
                        //判断后续的数值
                        a = b;
                        b = c;
                        a_len_temp = b_len_temp;
                        b_len_temp = c_len;
                        c_pos = c_pos + c_len;
					}
                    else if (a + b > c) 
                        ++c_len;//增长c的长度
                    else if (a + b < c) 
                        break;
                    if (c_pos == num.size())
                        return 1; //判断到结尾
				}
                ++b_len;
            }
            ++a_len;
        }


        return 0;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值