leetCode824:将数组拆分成斐波那契序列

目录

一、题目描述

二、解题思路

三、代码实现


一、题目描述

给定一个数字字符串 S,比如 S = "123456579",我们可以将它分成斐波那契式的序列 [123, 456, 579]。

形式上,斐波那契式序列是一个非负整数列表 F,且满足:

  • 0 <= F[i] <= 2^31 - 1,(也就是说,每个整数都符合 32 位有符号整数类型);
  • F.length >= 3;
  • 对于所有的0 <= i < F.length - 2,都有 F[i] + F[i+1] = F[i+2] 成立。

另外,请注意,将字符串拆分成小块时,每个块的数字一定不要以零开头,除非这个块是数字 0 本身。

返回从 S 拆分出来的任意一组斐波那契式的序列块,如果不能拆分则返回 []。

 

示例 1:

输入:"123456579"
输出:[123,456,579]

示例 2:

输入: "11235813"
输出: [1,1,2,3,5,8,13]

示例 3:

输入: "112358130"
输出: []
解释: 这项任务无法完成。

示例 4:

输入:"0123"
输出:[]
解释:每个块的数字不能以零开头,因此 "01","2","3" 不是有效答案。

示例 5:

输入: "1101111"
输出: [110, 1, 111]
解释: 输出 [11,0,11,11] 也同样被接受。
 

提示:

  1. 1 <= S.length <= 200
  2. 字符串 S 中只含有数字。

二、解题思路

这题是经典的回溯算法的题。

个人经验是学习任何一种新的算法思想,在理解了理论知识后加以适当的练习,才能把这种思想熟练的掌握,如果练题量不足的话,后面遇到经典直接的题也许会做,但是如果稍加变化,可能就不会做了。练题的目的是为了积累经验,有了经验之后做题就是记忆反射加上一些小变化了。没错,说的就是我练题不够…

关于回溯算法,个人的一些小经验(练题并不多,并不能保证正确):

回溯算法有两种基本特征:
  1、每一步可能有多个可选项,一开始时并不知道该选哪一个(选哪一个都有可能);
  2、每一步的选择有连锁反应,当某一步的选择不满足要求时则需要回退一步再继续选择试探。

说回本题,本题的可选项是选择哪几个字符构建成一个数字并不确定,只有当所有的数字都构建完了,并且满足斐波那契数列的形式则算构建成功;所以只有循环遍历所有可能的字符串前缀,查看是否满足要求,如果满足要求就把构建的数组返回。另外注意dfs剪枝的情况:数字不能有前置0;整形和存在越界情况。

三、代码实现

#include <bits/stdc++.h>
using namespace std;

vector<int> res;
bool backtrack(string s, int index) {
	//递归出口:字符串走完了,并且数组元素个数大于等于3
	if (index == s.size() && res.size() >= 3)  return true;
	long long curr = 0;
	//循环遍历每一个字符,寻找一个可能满足要求的数字
	for (int i = index; i < s.size(); i++) {
		//前置0直接不能成功划分
		if (i > index && s[index] == '0')  return false;
		curr = curr * 10 + s[i] - '0';
		//当前划分出的数字已经大于int的最大值了,后续只能会更大了,不用继续再分
		if (curr > INT_MAX)  return false;
		//将得到的满足要求的数字放进数组中,注意int型数据越界的问题
		if (res.size() < 2 || (long long)res[res.size() - 2] + (long long)res[res.size() - 1] == curr) {
			res.push_back(curr);
			//对后续字符继续划分,如果成功划分,返回true
			if (backtrack(s, i + 1)) {
				return true;
			}
			//划分不成功说明需要回溯
			res.pop_back();
		}
	}
	return false;
}
vector<int> splitIntoFibonacci(string S) {
	backtrack(S, 0);
	return res;
}

int main() {
	string S = "11235813";
	vector<int> ans = splitIntoFibonacci(S);
	for (auto& x : ans) {
		cout << x << " ";
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值