Additive Number 累加数

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

一个有效的累加序列必须至少包含 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

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

思路:对于这类把输入字符串进行切分,然后看是否满足某种规律的题目可以参考Palindrome Partitioning 分割回文串的通用公式,注意这和组合的情况的不一样,组合是从n个中选择m个,剩下的n-m个就不用了,和这种把一个字符串进行划分的还不一样。下面先给出通用公式:

void partitionCore(vector<vector<string>> &res, vector<string> &curStr, string &s ,int start) {
	if (start == (s.size())) {
		res.push_back(curStr);
	}
	for (int i = start; i < s.size(); i++) {
		if (isPlidrom(s, start, i)) {
			curStr.push_back(s.substr(start,(i-start+1)));
			partitionCore(res, curStr, s, i + 1);
			curStr.pop_back();
		}
		
	}
}

这部分是核心代码,在递归的开始部分先做判断:如果当前的下标start到了给定字符串的长度,就做blabla。。。然后从i=start开始,一直遍历到s的长度,在每次遍历过程中,我们都需要先把字符串从start~i(包括i)进行切割,然后放入临时字符串中,观察临时字符串是否满足某种规律,如果满足就把当前临时字符串放入结果中。

那么同理,我们用上面的模板来套这道题,只不过多了几个判断。

1因为只要满足一个条件就可以,所以我们在参数中设置一个引用bool的flag,如果找到的话直接返回结果,不再寻找。

2由于要满足斐波那契的规律:G(n-2)+G(n-1)=G(n),所以我们需要一个数组来存储已经找到的数字,而且还需要处理大数字的问题,所以需要几个辅助函数:

2.1判断数组的最后两个数字和新数字cur是否满足规律:G(n-2)+G(n-1)=G(n)

bool isSequece(vector<long long int> &res,long long int cur)

2.2判断一个字符串是否是无效字符串,主要是01,02这样有前导0的

bool isvalid(string &str)

2.3把一个string转为long long int(为了避免数字溢出,用long long int类型)

long long int string_int(string &str)

最后看核心代码:

void isAdditiveNumber(vector<long long int> &res, string &num, bool &flag, int start) {
	
	if (flag || start == num.size()) {
		if (res.size() >= 3) {
			flag = true;
		}
		return;
	}
	for (int i = start; i < num.size(); i++) {
		string sub = (num.substr(start, i - start + 1));
		if (!isvalid(sub)) break;
		long long int temp = string_int(sub);
		if (res.size() < 2) {
			res.push_back(temp);
			isAdditiveNumber(res,num,flag,i+1);
			res.pop_back();
		}
		else {
			if (isSequece(res, temp)) {
				res.push_back(temp);
				isAdditiveNumber(res, num, flag, i + 1);
				res.pop_back();
			}
		}
		if (flag) return;
	}
}

这里有分叉处理,如果当前res的长度小于2,那么先放进去res中(因为规律必须要至少3个数才能判断),最后加了剪纸判断,如果已经找到了直接返回true,不再继续寻找。

参考代码:

class Solution {
public:
bool isSequece(vector<long long int> &res,long long int cur) {
	if (res.size() >= 2) {
		if ((res[res.size() - 1] + res[res.size() - 2]) == cur) {
			return true;
		}
	}
	return false;
}
bool isvalid(string &str) {
	if ((str.size() > 1) && str[0] == '0') return false;
	return true;
}
long long int string_int(string &str) {
	long long int res = 0;
	for (int i = 0; i < str.size(); i++) {
		res = res * 10 + (str[i] - '0');
	}
	return res;
}
void isAdditiveNumber(vector<long long int> &res, string &num, bool &flag, int start) {
	
	if (flag || start == num.size()) {
		if (res.size() >= 3) {
			flag = true;
		}
		return;
	}
	for (int i = start; i < num.size(); i++) {
		string sub = (num.substr(start, i - start + 1));
		if (!isvalid(sub)) break;
		long long int temp = string_int(sub);
		if (res.size() < 2) {
			res.push_back(temp);
			isAdditiveNumber(res,num,flag,i+1);
			res.pop_back();
		}
		else {
			if (isSequece(res, temp)) {
				res.push_back(temp);
				isAdditiveNumber(res, num, flag, i + 1);
				res.pop_back();
			}
		}
		if (flag) return;
	}
}

bool isAdditiveNumber(string num) {
	bool flag = false;
	vector<long long int> res;
	isAdditiveNumber(res, num, flag,0);
	return flag;
}
};

猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/81562336
今日推荐