力扣306(java)-累加数(中等)
题目:
累加数 是一个字符串,组成它的数字可以形成累加序列。
一个有效的 累加序列 必须 至少 包含 3 个数。除了最开始的两个数以外,序列中的每个后续数字必须是它之前两个数字之和。
给你一个只包含数字 '0'-'9' 的字符串,编写一个算法来判断给定输入是否是 累加数 。如果是,返回 true ;否则,返回 false 。
说明:累加序列里的数,除数字 0 之外,不会 以 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
提示:
1 <= num.length <= 35
num 仅由数字(0 - 9)组成
进阶:你计划如何处理由过大的整数输入导致的溢出?
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/additive-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
看了各个大佬的解析:使用递归+剪枝的思路:
递归:
对字符串拆分来生成数字,从第三个数开始,需要判断拆分出的数是否等于前两个数的和,相等则进行拆分,继续寻找下一个数,如果不相等,则不进行拆分,继续循环拼接生成新的数。
剪枝:
1.前导零:0可以作为单独数,但如果第一个数为零,当前字符不为第一个字符,就会出现前导零(01,02),则不会继续向下拼接;
2.第三个数开始,如果当前生成数比前两个数的和大,则也不继续向下拼接,如果当前生成数比前两个数和小,则继续拼接新的字符。
代码:
1 class Solution { 2 public boolean isAdditiveNumber(String num) { 3 return dfs(num, 0, 0, 0, 0); 4 } 5 //index:当前的下标, count:生成数的个数, previous:前一个数的值, sum:前两个数的和 6 public boolean dfs(String num, int index, int count, long previous, long sum){ 7 //生成数必须要有三个 8 if(index >= num.length()){ 9 return count >= 3; 10 } 11 //拼接数的值 12 long current = 0; 13 for(int i = index; i < num.length(); i++){ 14 char c = num.charAt(i); 15 16 //第一个字符为0,但是当前字符不为第一个字符,则为前导0(01,02) 17 if(num.charAt(index) == '0' && i != index){ 18 return false; 19 } 20 21 //计算数值 22 current = current * 10 + c - '0'; 23 //如果前面已经存在合法的两个数,则判断第三个数是否为前两个数的和 24 if(count >= 2){ 25 if(current < sum){ 26 //当前数比前两个数小,还可以继续加新的字符 27 continue; 28 } 29 if(current > sum){ 30 //当前数比前两个数大,不能成为累加 31 return false; 32 } 33 } 34 //使用当前数向下递归,下标+1,个数+1,前一个数的值为current,前面数的和需加上current 35 if(dfs(num, i+1, count+1, current, previous + current)){ 36 return true; 37 } 38 } 39 return false; 40 41 } 42 }