​LeetCode刷题实战306:累加数

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 累加数,我们先来看题面:

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

Additive number is a string whose digits can form additive sequence.

A valid additive sequence should contain at least three numbers. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two.

Given a string containing only digits '0'-'9', write a function to determine if it's an additive number.

Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid.

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

一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。

给定一个只包含数字 '0'-'9' 的字符串,编写一个算法来判断给定输入是否是累加数。

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

示例

示例 1:

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

示例 2:

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

进阶:
你如何处理一个溢出的过大的整数输入?

解题

https://blog.youkuaiyun.com/qq_23523409/article/details/84585030

解题思路:

数字字符串加法,DFS。其实一开始选择好两个相加的字符串就已经能确定,它们是否能够一直加到最后。

假设对于原始的字符串num,长度是size.

  1. 我们选择str1=num.substr(0,len1),str2 = num.substr(len1,len2)。满足str1.size()+str2.size()<num.size()。很容易发现len1=[1,size/2],len2=[1,size/2]为两个长度的取值范围,都是闭区间。

  2. 选择一个len1,len2组合,剩余字符串为str3 = num.substr(len1+len2,size-len1-len2)。深度搜索DFS(str1,str2,str3)。

  3. 为了处理溢出的过大的整数,不采用转整数的方式,而是采取字符串相加的原则。add(str1,str2)为两个数字字符串相加的结果。

  4. 如果add(str1,str2)==str3,那么return true;否则至少str3的其中一个前缀是add(str1,str2),继续搜索下一步搜索。其余都可以return false。

  5. 如果找到一个合适的组合,return true,如果最终发现len1,len2这个组合不行,更改组合,重复3-5。如果所有组合都不行,那么最后return false。

注意事项:

累加项不以0开头,实质上不严格。如果只是不以0开头,那么0必然不存在,事实并不是。严格的逻辑是除0以外,不以0开头。

class Solution {
public:
    bool isAdditiveNumber(string num) {
        int size = num.size();
        if (size <= 2) return false;
        string str1, str2, str3;
        int len1, len2;
        for (len1 = 1; len1 <= size / 2; len1++) {
            str1 = num.substr(0, len1);
            for (len2 = 1; len2 <= size / 2; len2++) {
                str2 = num.substr(len1, len2);
                str3 = num.substr(len1 + len2, size - len1 - len2);
                if (DFS(str1, str2, str3)) return true;
            }
        }
        return false;
    }
    bool DFS(string first,string second,string last) {
        if (first[0] == '0'&&first != "0" || second[0] == '0'&&second != "0") return false;
        string addstr = add(first, second);
        if (addstr.size() > last.size()) return false;
        if (addstr == last) return true;
        int size = addstr.size();
        if (addstr != last.substr(0, size)) return false;
        first = second; 
        second = addstr; 
        last = last.substr(size, int(last.size()) - size);
        return DFS(first, second, last);
    }
    string add(string str1, string str2) {        
        if (str1.size() < str2.size()) swap(str1, str2);
        int size1 = str1.size();
        int size2 = str2.size();
        str2 = string(size1 - size2, '0') + str2;
        int sgn = 0;
        for (int i = size1; i >= 1; i--) {
            int nums = str1[i - 1] - '0' + str2[i - 1] - '0' + sgn;
            str1[i - 1] = nums % 10 + '0';
            sgn = nums / 10;
        }
        if (sgn == 1) str1 = "1" + str1;
        return str1;
    }
};

好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:

LeetCode1-280题汇总,希望对你有点帮助!

LeetCode刷题实战301:删除无效的括号

LeetCode刷题实战302:包含全部黑色像素的最小矩阵

LeetCode刷题实战303:区域和检索 - 数组不可变

LeetCode刷题实战304:二维区域和检索 - 矩阵不可变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值